1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
4 * Portions Copyright (c) 2013 Company 100 Inc. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 * THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29#include "DataReference.h"
30#include "WebCoreArgumentCoders.h"
31
32#include <WebCore/CertificateInfo.h>
33#include <WebCore/DictionaryPopupInfo.h>
34#include <WebCore/FontAttributes.h>
35#include <WebCore/ResourceError.h>
36#include <WebCore/ResourceRequest.h>
37#include <WebCore/ResourceResponse.h>
38#include <WebCore/SoupNetworkProxySettings.h>
39#include <wtf/text/CString.h>
40
41namespace IPC {
42using namespace WebCore;
43
44void ArgumentCoder<ResourceRequest>::encodePlatformData(Encoder& encoder, const ResourceRequest& resourceRequest)
45{
46 resourceRequest.encodeWithPlatformData(encoder);
47}
48
49bool ArgumentCoder<ResourceRequest>::decodePlatformData(Decoder& decoder, ResourceRequest& resourceRequest)
50{
51 return resourceRequest.decodeWithPlatformData(decoder);
52}
53
54void ArgumentCoder<CertificateInfo>::encode(Encoder& encoder, const CertificateInfo& certificateInfo)
55{
56 auto* certificate = certificateInfo.certificate();
57 if (!certificate) {
58 encoder << 0;
59 return;
60 }
61
62 Vector<GRefPtr<GByteArray>> certificatesDataList;
63 for (; certificate; certificate = g_tls_certificate_get_issuer(certificate)) {
64 GByteArray* certificateData = nullptr;
65 g_object_get(G_OBJECT(certificate), "certificate", &certificateData, nullptr);
66
67 if (!certificateData) {
68 certificatesDataList.clear();
69 break;
70 }
71
72 certificatesDataList.append(adoptGRef(certificateData));
73 }
74
75 encoder << static_cast<uint32_t>(certificatesDataList.size());
76
77 if (certificatesDataList.isEmpty())
78 return;
79
80 // Encode starting from the root certificate.
81 for (size_t i = certificatesDataList.size(); i > 0; --i) {
82 GByteArray* certificate = certificatesDataList[i - 1].get();
83 encoder.encodeVariableLengthByteArray(IPC::DataReference(certificate->data, certificate->len));
84 }
85
86 encoder << static_cast<uint32_t>(certificateInfo.tlsErrors());
87}
88
89bool ArgumentCoder<CertificateInfo>::decode(Decoder& decoder, CertificateInfo& certificateInfo)
90{
91 uint32_t chainLength;
92 if (!decoder.decode(chainLength))
93 return false;
94
95 if (!chainLength)
96 return true;
97
98 GType certificateType = g_tls_backend_get_certificate_type(g_tls_backend_get_default());
99 GRefPtr<GTlsCertificate> certificate;
100 for (uint32_t i = 0; i < chainLength; i++) {
101 IPC::DataReference certificateDataReference;
102 if (!decoder.decodeVariableLengthByteArray(certificateDataReference))
103 return false;
104
105 GByteArray* certificateData = g_byte_array_sized_new(certificateDataReference.size());
106 GRefPtr<GByteArray> certificateBytes = adoptGRef(g_byte_array_append(certificateData, certificateDataReference.data(), certificateDataReference.size()));
107
108 certificate = adoptGRef(G_TLS_CERTIFICATE(g_initable_new(
109 certificateType, nullptr, nullptr, "certificate", certificateBytes.get(), "issuer", certificate.get(), nullptr)));
110 }
111
112 uint32_t tlsErrors;
113 if (!decoder.decode(tlsErrors))
114 return false;
115
116 certificateInfo.setCertificate(certificate.get());
117 certificateInfo.setTLSErrors(static_cast<GTlsCertificateFlags>(tlsErrors));
118
119 return true;
120}
121
122void ArgumentCoder<ResourceError>::encodePlatformData(Encoder& encoder, const ResourceError& resourceError)
123{
124 encoder << resourceError.domain();
125 encoder << resourceError.errorCode();
126 encoder << resourceError.failingURL().string();
127 encoder << resourceError.localizedDescription();
128
129 encoder << CertificateInfo(resourceError);
130}
131
132bool ArgumentCoder<ResourceError>::decodePlatformData(Decoder& decoder, ResourceError& resourceError)
133{
134 String domain;
135 if (!decoder.decode(domain))
136 return false;
137
138 int errorCode;
139 if (!decoder.decode(errorCode))
140 return false;
141
142 String failingURL;
143 if (!decoder.decode(failingURL))
144 return false;
145
146 String localizedDescription;
147 if (!decoder.decode(localizedDescription))
148 return false;
149
150 resourceError = ResourceError(domain, errorCode, URL(URL(), failingURL), localizedDescription);
151
152 CertificateInfo certificateInfo;
153 if (!decoder.decode(certificateInfo))
154 return false;
155
156 resourceError.setCertificate(certificateInfo.certificate());
157 resourceError.setTLSErrors(certificateInfo.tlsErrors());
158 return true;
159}
160
161void ArgumentCoder<SoupNetworkProxySettings>::encode(Encoder& encoder, const SoupNetworkProxySettings& settings)
162{
163 ASSERT(!settings.isEmpty());
164 encoder.encodeEnum(settings.mode);
165 if (settings.mode != SoupNetworkProxySettings::Mode::Custom)
166 return;
167
168 encoder << settings.defaultProxyURL;
169 uint32_t ignoreHostsCount = settings.ignoreHosts ? g_strv_length(settings.ignoreHosts.get()) : 0;
170 encoder << ignoreHostsCount;
171 if (ignoreHostsCount) {
172 for (uint32_t i = 0; settings.ignoreHosts.get()[i]; ++i)
173 encoder << CString(settings.ignoreHosts.get()[i]);
174 }
175 encoder << settings.proxyMap;
176}
177
178bool ArgumentCoder<SoupNetworkProxySettings>::decode(Decoder& decoder, SoupNetworkProxySettings& settings)
179{
180 if (!decoder.decodeEnum(settings.mode))
181 return false;
182
183 if (settings.mode != SoupNetworkProxySettings::Mode::Custom)
184 return true;
185
186 if (!decoder.decode(settings.defaultProxyURL))
187 return false;
188
189 uint32_t ignoreHostsCount;
190 if (!decoder.decode(ignoreHostsCount))
191 return false;
192
193 if (ignoreHostsCount) {
194 settings.ignoreHosts.reset(g_new0(char*, ignoreHostsCount + 1));
195 for (uint32_t i = 0; i < ignoreHostsCount; ++i) {
196 CString host;
197 if (!decoder.decode(host))
198 return false;
199
200 settings.ignoreHosts.get()[i] = g_strdup(host.data());
201 }
202 }
203
204 if (!decoder.decode(settings.proxyMap))
205 return false;
206
207 return !settings.isEmpty();
208}
209
210void ArgumentCoder<ProtectionSpace>::encodePlatformData(Encoder&, const ProtectionSpace&)
211{
212 ASSERT_NOT_REACHED();
213}
214
215bool ArgumentCoder<ProtectionSpace>::decodePlatformData(Decoder&, ProtectionSpace&)
216{
217 ASSERT_NOT_REACHED();
218 return false;
219}
220
221void ArgumentCoder<Credential>::encodePlatformData(Encoder&, const Credential&)
222{
223 ASSERT_NOT_REACHED();
224}
225
226bool ArgumentCoder<Credential>::decodePlatformData(Decoder&, Credential&)
227{
228 ASSERT_NOT_REACHED();
229 return false;
230}
231
232void ArgumentCoder<FontAttributes>::encodePlatformData(Encoder&, const FontAttributes&)
233{
234 ASSERT_NOT_REACHED();
235}
236
237Optional<FontAttributes> ArgumentCoder<FontAttributes>::decodePlatformData(Decoder&, FontAttributes&)
238{
239 ASSERT_NOT_REACHED();
240 return WTF::nullopt;
241}
242
243void ArgumentCoder<DictionaryPopupInfo>::encodePlatformData(Encoder&, const DictionaryPopupInfo&)
244{
245 ASSERT_NOT_REACHED();
246}
247
248bool ArgumentCoder<DictionaryPopupInfo>::decodePlatformData(Decoder&, DictionaryPopupInfo&)
249{
250 ASSERT_NOT_REACHED();
251 return false;
252}
253
254}
255
256