1 /*
2  * Copyright (C) 2009 Google 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "third_party/blink/public/platform/web_url_response.h"
32 
33 #include <algorithm>
34 #include <memory>
35 #include <utility>
36 
37 #include "base/memory/ptr_util.h"
38 #include "base/memory/scoped_refptr.h"
39 #include "services/network/public/mojom/load_timing_info.mojom.h"
40 #include "third_party/blink/public/platform/web_http_header_visitor.h"
41 #include "third_party/blink/public/platform/web_http_load_info.h"
42 #include "third_party/blink/public/platform/web_string.h"
43 #include "third_party/blink/public/platform/web_url.h"
44 #include "third_party/blink/renderer/platform/loader/fetch/resource_load_info.h"
45 #include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
46 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
47 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
48 #include "third_party/blink/renderer/platform/wtf/assertions.h"
49 
50 namespace blink {
51 
52 WebURLResponse::~WebURLResponse() = default;
53 
WebURLResponse()54 WebURLResponse::WebURLResponse()
55     : owned_resource_response_(std::make_unique<ResourceResponse>()),
56       resource_response_(owned_resource_response_.get()) {}
57 
WebURLResponse(const WebURLResponse & r)58 WebURLResponse::WebURLResponse(const WebURLResponse& r)
59     : owned_resource_response_(
60           std::make_unique<ResourceResponse>(*r.resource_response_)),
61       resource_response_(owned_resource_response_.get()) {}
62 
WebURLResponse(const WebURL & current_request_url)63 WebURLResponse::WebURLResponse(const WebURL& current_request_url)
64     : WebURLResponse() {
65   SetCurrentRequestUrl(current_request_url);
66 }
67 
operator =(const WebURLResponse & r)68 WebURLResponse& WebURLResponse::operator=(const WebURLResponse& r) {
69   // Copying subclasses that have different m_resourceResponse ownership
70   // semantics via this operator is just not supported.
71   DCHECK(owned_resource_response_);
72   DCHECK(resource_response_);
73   if (&r != this)
74     *resource_response_ = *r.resource_response_;
75   return *this;
76 }
77 
IsNull() const78 bool WebURLResponse::IsNull() const {
79   return resource_response_->IsNull();
80 }
81 
CurrentRequestUrl() const82 WebURL WebURLResponse::CurrentRequestUrl() const {
83   return resource_response_->CurrentRequestUrl();
84 }
85 
SetCurrentRequestUrl(const WebURL & url)86 void WebURLResponse::SetCurrentRequestUrl(const WebURL& url) {
87   resource_response_->SetCurrentRequestUrl(url);
88 }
89 
ResponseUrl() const90 WebURL WebURLResponse::ResponseUrl() const {
91   return resource_response_->ResponseUrl();
92 }
93 
SetConnectionID(unsigned connection_id)94 void WebURLResponse::SetConnectionID(unsigned connection_id) {
95   resource_response_->SetConnectionID(connection_id);
96 }
97 
SetConnectionReused(bool connection_reused)98 void WebURLResponse::SetConnectionReused(bool connection_reused) {
99   resource_response_->SetConnectionReused(connection_reused);
100 }
101 
SetLoadTiming(const network::mojom::LoadTimingInfo & mojo_timing)102 void WebURLResponse::SetLoadTiming(
103     const network::mojom::LoadTimingInfo& mojo_timing) {
104   auto timing = ResourceLoadTiming::Create();
105   timing->SetRequestTime(mojo_timing.request_start);
106   timing->SetProxyStart(mojo_timing.proxy_resolve_start);
107   timing->SetProxyEnd(mojo_timing.proxy_resolve_end);
108   timing->SetDnsStart(mojo_timing.connect_timing.dns_start);
109   timing->SetDnsEnd(mojo_timing.connect_timing.dns_end);
110   timing->SetConnectStart(mojo_timing.connect_timing.connect_start);
111   timing->SetConnectEnd(mojo_timing.connect_timing.connect_end);
112   timing->SetWorkerStart(mojo_timing.service_worker_start_time);
113   timing->SetWorkerReady(mojo_timing.service_worker_ready_time);
114   timing->SetSendStart(mojo_timing.send_start);
115   timing->SetSendEnd(mojo_timing.send_end);
116   timing->SetReceiveHeadersStart(mojo_timing.receive_headers_start);
117   timing->SetReceiveHeadersEnd(mojo_timing.receive_headers_end);
118   timing->SetSslStart(mojo_timing.connect_timing.ssl_start);
119   timing->SetSslEnd(mojo_timing.connect_timing.ssl_end);
120   timing->SetPushStart(mojo_timing.push_start);
121   timing->SetPushEnd(mojo_timing.push_end);
122   resource_response_->SetResourceLoadTiming(std::move(timing));
123 }
124 
SetHTTPLoadInfo(const WebHTTPLoadInfo & value)125 void WebURLResponse::SetHTTPLoadInfo(const WebHTTPLoadInfo& value) {
126   resource_response_->SetResourceLoadInfo(value);
127 }
128 
SetResponseTime(base::Time response_time)129 void WebURLResponse::SetResponseTime(base::Time response_time) {
130   resource_response_->SetResponseTime(response_time);
131 }
132 
MimeType() const133 WebString WebURLResponse::MimeType() const {
134   return resource_response_->MimeType();
135 }
136 
SetMimeType(const WebString & mime_type)137 void WebURLResponse::SetMimeType(const WebString& mime_type) {
138   resource_response_->SetMimeType(mime_type);
139 }
140 
ExpectedContentLength() const141 int64_t WebURLResponse::ExpectedContentLength() const {
142   return resource_response_->ExpectedContentLength();
143 }
144 
SetExpectedContentLength(int64_t expected_content_length)145 void WebURLResponse::SetExpectedContentLength(int64_t expected_content_length) {
146   resource_response_->SetExpectedContentLength(expected_content_length);
147 }
148 
SetTextEncodingName(const WebString & text_encoding_name)149 void WebURLResponse::SetTextEncodingName(const WebString& text_encoding_name) {
150   resource_response_->SetTextEncodingName(text_encoding_name);
151 }
152 
HttpVersion() const153 WebURLResponse::HTTPVersion WebURLResponse::HttpVersion() const {
154   return static_cast<HTTPVersion>(resource_response_->HttpVersion());
155 }
156 
SetHttpVersion(HTTPVersion version)157 void WebURLResponse::SetHttpVersion(HTTPVersion version) {
158   resource_response_->SetHttpVersion(
159       static_cast<ResourceResponse::HTTPVersion>(version));
160 }
161 
RequestId() const162 int WebURLResponse::RequestId() const {
163   return resource_response_->RequestId();
164 }
165 
SetRequestId(int request_id)166 void WebURLResponse::SetRequestId(int request_id) {
167   resource_response_->SetRequestId(request_id);
168 }
169 
HttpStatusCode() const170 int WebURLResponse::HttpStatusCode() const {
171   return resource_response_->HttpStatusCode();
172 }
173 
SetHttpStatusCode(int http_status_code)174 void WebURLResponse::SetHttpStatusCode(int http_status_code) {
175   resource_response_->SetHttpStatusCode(http_status_code);
176 }
177 
HttpStatusText() const178 WebString WebURLResponse::HttpStatusText() const {
179   return resource_response_->HttpStatusText();
180 }
181 
SetHttpStatusText(const WebString & http_status_text)182 void WebURLResponse::SetHttpStatusText(const WebString& http_status_text) {
183   resource_response_->SetHttpStatusText(http_status_text);
184 }
185 
HttpHeaderField(const WebString & name) const186 WebString WebURLResponse::HttpHeaderField(const WebString& name) const {
187   return resource_response_->HttpHeaderField(name);
188 }
189 
SetHttpHeaderField(const WebString & name,const WebString & value)190 void WebURLResponse::SetHttpHeaderField(const WebString& name,
191                                         const WebString& value) {
192   resource_response_->SetHttpHeaderField(name, value);
193 }
194 
AddHttpHeaderField(const WebString & name,const WebString & value)195 void WebURLResponse::AddHttpHeaderField(const WebString& name,
196                                         const WebString& value) {
197   if (name.IsNull() || value.IsNull())
198     return;
199 
200   resource_response_->AddHttpHeaderField(name, value);
201 }
202 
ClearHttpHeaderField(const WebString & name)203 void WebURLResponse::ClearHttpHeaderField(const WebString& name) {
204   resource_response_->ClearHttpHeaderField(name);
205 }
206 
VisitHttpHeaderFields(WebHTTPHeaderVisitor * visitor) const207 void WebURLResponse::VisitHttpHeaderFields(
208     WebHTTPHeaderVisitor* visitor) const {
209   const HTTPHeaderMap& map = resource_response_->HttpHeaderFields();
210   for (HTTPHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it)
211     visitor->VisitHeader(it->key, it->value);
212 }
213 
AppCacheID() const214 int64_t WebURLResponse::AppCacheID() const {
215   return resource_response_->AppCacheID();
216 }
217 
SetAppCacheID(int64_t app_cache_id)218 void WebURLResponse::SetAppCacheID(int64_t app_cache_id) {
219   resource_response_->SetAppCacheID(app_cache_id);
220 }
221 
AppCacheManifestURL() const222 WebURL WebURLResponse::AppCacheManifestURL() const {
223   return resource_response_->AppCacheManifestURL();
224 }
225 
SetAppCacheManifestURL(const WebURL & url)226 void WebURLResponse::SetAppCacheManifestURL(const WebURL& url) {
227   resource_response_->SetAppCacheManifestURL(url);
228 }
229 
SetHasMajorCertificateErrors(bool value)230 void WebURLResponse::SetHasMajorCertificateErrors(bool value) {
231   resource_response_->SetHasMajorCertificateErrors(value);
232 }
233 
SetCTPolicyCompliance(net::ct::CTPolicyCompliance compliance)234 void WebURLResponse::SetCTPolicyCompliance(
235     net::ct::CTPolicyCompliance compliance) {
236   switch (compliance) {
237     case net::ct::CTPolicyCompliance::
238         CT_POLICY_COMPLIANCE_DETAILS_NOT_AVAILABLE:
239     case net::ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY:
240       resource_response_->SetCTPolicyCompliance(
241           ResourceResponse::kCTPolicyComplianceDetailsNotAvailable);
242       break;
243     case net::ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS:
244     case net::ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS:
245       resource_response_->SetCTPolicyCompliance(
246           ResourceResponse::kCTPolicyDoesNotComply);
247       break;
248     case net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS:
249       resource_response_->SetCTPolicyCompliance(
250           ResourceResponse::kCTPolicyComplies);
251       break;
252     case net::ct::CTPolicyCompliance::CT_POLICY_COUNT:
253       NOTREACHED();
254       resource_response_->SetCTPolicyCompliance(
255           ResourceResponse::kCTPolicyComplianceDetailsNotAvailable);
256       break;
257   };
258 }
259 
SetIsLegacyTLSVersion(bool value)260 void WebURLResponse::SetIsLegacyTLSVersion(bool value) {
261   resource_response_->SetIsLegacyTLSVersion(value);
262 }
263 
SetTimingAllowPassed(bool value)264 void WebURLResponse::SetTimingAllowPassed(bool value) {
265   resource_response_->SetTimingAllowPassed(value);
266 }
267 
SetSecurityStyle(SecurityStyle security_style)268 void WebURLResponse::SetSecurityStyle(SecurityStyle security_style) {
269   resource_response_->SetSecurityStyle(security_style);
270 }
271 
SetSecurityDetails(const WebSecurityDetails & web_security_details)272 void WebURLResponse::SetSecurityDetails(
273     const WebSecurityDetails& web_security_details) {
274   ResourceResponse::SignedCertificateTimestampList sct_list;
275   for (const auto& iter : web_security_details.sct_list) {
276     sct_list.push_back(
277         static_cast<ResourceResponse::SignedCertificateTimestamp>(iter));
278   }
279   Vector<String> san_list;
280   san_list.Append(web_security_details.san_list.Data(),
281                   web_security_details.san_list.size());
282   Vector<AtomicString> certificate;
283   for (const auto& iter : web_security_details.certificate) {
284     AtomicString cert = iter;
285     certificate.push_back(cert);
286   }
287   resource_response_->SetSecurityDetails(
288       web_security_details.protocol, web_security_details.key_exchange,
289       web_security_details.key_exchange_group, web_security_details.cipher,
290       web_security_details.mac, web_security_details.subject_name, san_list,
291       web_security_details.issuer,
292       static_cast<time_t>(web_security_details.valid_from),
293       static_cast<time_t>(web_security_details.valid_to), certificate,
294       sct_list);
295 }
296 
297 base::Optional<WebURLResponse::WebSecurityDetails>
SecurityDetailsForTesting()298 WebURLResponse::SecurityDetailsForTesting() {
299   const base::Optional<ResourceResponse::SecurityDetails>& security_details =
300       resource_response_->GetSecurityDetails();
301   if (!security_details.has_value())
302     return base::nullopt;
303   SignedCertificateTimestampList sct_list;
304   for (const auto& iter : security_details->sct_list) {
305     sct_list.emplace_back(SignedCertificateTimestamp(
306         iter.status_, iter.origin_, iter.log_description_, iter.log_id_,
307         iter.timestamp_, iter.hash_algorithm_, iter.signature_algorithm_,
308         iter.signature_data_));
309   }
310   return WebSecurityDetails(
311       security_details->protocol, security_details->key_exchange,
312       security_details->key_exchange_group, security_details->cipher,
313       security_details->mac, security_details->subject_name,
314       security_details->san_list, security_details->issuer,
315       security_details->valid_from, security_details->valid_to,
316       security_details->certificate, sct_list);
317 }
318 
ToResourceResponse() const319 const ResourceResponse& WebURLResponse::ToResourceResponse() const {
320   return *resource_response_;
321 }
322 
SetWasCached(bool value)323 void WebURLResponse::SetWasCached(bool value) {
324   resource_response_->SetWasCached(value);
325 }
326 
WasFetchedViaSPDY() const327 bool WebURLResponse::WasFetchedViaSPDY() const {
328   return resource_response_->WasFetchedViaSPDY();
329 }
330 
SetWasFetchedViaSPDY(bool value)331 void WebURLResponse::SetWasFetchedViaSPDY(bool value) {
332   resource_response_->SetWasFetchedViaSPDY(value);
333 }
334 
WasFetchedViaServiceWorker() const335 bool WebURLResponse::WasFetchedViaServiceWorker() const {
336   return resource_response_->WasFetchedViaServiceWorker();
337 }
338 
SetWasFetchedViaServiceWorker(bool value)339 void WebURLResponse::SetWasFetchedViaServiceWorker(bool value) {
340   resource_response_->SetWasFetchedViaServiceWorker(value);
341 }
342 
SetWasFallbackRequiredByServiceWorker(bool value)343 void WebURLResponse::SetWasFallbackRequiredByServiceWorker(bool value) {
344   resource_response_->SetWasFallbackRequiredByServiceWorker(value);
345 }
346 
SetType(network::mojom::FetchResponseType value)347 void WebURLResponse::SetType(network::mojom::FetchResponseType value) {
348   resource_response_->SetType(value);
349 }
350 
GetType() const351 network::mojom::FetchResponseType WebURLResponse::GetType() const {
352   return resource_response_->GetType();
353 }
354 
SetUrlListViaServiceWorker(const WebVector<WebURL> & url_list_via_service_worker)355 void WebURLResponse::SetUrlListViaServiceWorker(
356     const WebVector<WebURL>& url_list_via_service_worker) {
357   Vector<KURL> url_list(url_list_via_service_worker.size());
358   std::transform(url_list_via_service_worker.begin(),
359                  url_list_via_service_worker.end(), url_list.begin(),
360                  [](const WebURL& url) { return url; });
361   resource_response_->SetUrlListViaServiceWorker(url_list);
362 }
363 
HasUrlListViaServiceWorker() const364 bool WebURLResponse::HasUrlListViaServiceWorker() const {
365   DCHECK(resource_response_->UrlListViaServiceWorker().size() == 0 ||
366          WasFetchedViaServiceWorker());
367   return resource_response_->UrlListViaServiceWorker().size() > 0;
368 }
369 
SetCacheStorageCacheName(const WebString & cache_storage_cache_name)370 void WebURLResponse::SetCacheStorageCacheName(
371     const WebString& cache_storage_cache_name) {
372   resource_response_->SetCacheStorageCacheName(cache_storage_cache_name);
373 }
374 
CorsExposedHeaderNames() const375 WebVector<WebString> WebURLResponse::CorsExposedHeaderNames() const {
376   return resource_response_->CorsExposedHeaderNames();
377 }
378 
SetCorsExposedHeaderNames(const WebVector<WebString> & header_names)379 void WebURLResponse::SetCorsExposedHeaderNames(
380     const WebVector<WebString>& header_names) {
381   Vector<String> exposed_header_names;
382   exposed_header_names.Append(header_names.Data(), header_names.size());
383   resource_response_->SetCorsExposedHeaderNames(exposed_header_names);
384 }
385 
SetDidServiceWorkerNavigationPreload(bool value)386 void WebURLResponse::SetDidServiceWorkerNavigationPreload(bool value) {
387   resource_response_->SetDidServiceWorkerNavigationPreload(value);
388 }
389 
RemoteIPAddress() const390 WebString WebURLResponse::RemoteIPAddress() const {
391   return resource_response_->RemoteIPAddress();
392 }
393 
SetRemoteIPAddress(const WebString & remote_ip_address)394 void WebURLResponse::SetRemoteIPAddress(const WebString& remote_ip_address) {
395   resource_response_->SetRemoteIPAddress(remote_ip_address);
396 }
397 
RemotePort() const398 uint16_t WebURLResponse::RemotePort() const {
399   return resource_response_->RemotePort();
400 }
401 
SetRemotePort(uint16_t remote_port)402 void WebURLResponse::SetRemotePort(uint16_t remote_port) {
403   resource_response_->SetRemotePort(remote_port);
404 }
405 
SetEncodedDataLength(int64_t length)406 void WebURLResponse::SetEncodedDataLength(int64_t length) {
407   resource_response_->SetEncodedDataLength(length);
408 }
409 
EncodedBodyLength() const410 int64_t WebURLResponse::EncodedBodyLength() const {
411   return resource_response_->EncodedBodyLength();
412 }
413 
SetEncodedBodyLength(int64_t length)414 void WebURLResponse::SetEncodedBodyLength(int64_t length) {
415   resource_response_->SetEncodedBodyLength(length);
416 }
417 
SetIsSignedExchangeInnerResponse(bool is_signed_exchange_inner_response)418 void WebURLResponse::SetIsSignedExchangeInnerResponse(
419     bool is_signed_exchange_inner_response) {
420   resource_response_->SetIsSignedExchangeInnerResponse(
421       is_signed_exchange_inner_response);
422 }
423 
SetWasInPrefetchCache(bool was_in_prefetch_cache)424 void WebURLResponse::SetWasInPrefetchCache(bool was_in_prefetch_cache) {
425   resource_response_->SetWasInPrefetchCache(was_in_prefetch_cache);
426 }
427 
SetRecursivePrefetchToken(const base::Optional<base::UnguessableToken> & token)428 void WebURLResponse::SetRecursivePrefetchToken(
429     const base::Optional<base::UnguessableToken>& token) {
430   resource_response_->SetRecursivePrefetchToken(token);
431 }
432 
WasAlpnNegotiated() const433 bool WebURLResponse::WasAlpnNegotiated() const {
434   return resource_response_->WasAlpnNegotiated();
435 }
436 
SetWasAlpnNegotiated(bool was_alpn_negotiated)437 void WebURLResponse::SetWasAlpnNegotiated(bool was_alpn_negotiated) {
438   resource_response_->SetWasAlpnNegotiated(was_alpn_negotiated);
439 }
440 
AlpnNegotiatedProtocol() const441 WebString WebURLResponse::AlpnNegotiatedProtocol() const {
442   return resource_response_->AlpnNegotiatedProtocol();
443 }
444 
SetAlpnNegotiatedProtocol(const WebString & alpn_negotiated_protocol)445 void WebURLResponse::SetAlpnNegotiatedProtocol(
446     const WebString& alpn_negotiated_protocol) {
447   resource_response_->SetAlpnNegotiatedProtocol(alpn_negotiated_protocol);
448 }
449 
WasAlternateProtocolAvailable() const450 bool WebURLResponse::WasAlternateProtocolAvailable() const {
451   return resource_response_->WasAlternateProtocolAvailable();
452 }
453 
SetWasAlternateProtocolAvailable(bool was_alternate_protocol_available)454 void WebURLResponse::SetWasAlternateProtocolAvailable(
455     bool was_alternate_protocol_available) {
456   resource_response_->SetWasAlternateProtocolAvailable(
457       was_alternate_protocol_available);
458 }
459 
ConnectionInfo() const460 net::HttpResponseInfo::ConnectionInfo WebURLResponse::ConnectionInfo() const {
461   return resource_response_->ConnectionInfo();
462 }
463 
SetConnectionInfo(net::HttpResponseInfo::ConnectionInfo connection_info)464 void WebURLResponse::SetConnectionInfo(
465     net::HttpResponseInfo::ConnectionInfo connection_info) {
466   resource_response_->SetConnectionInfo(connection_info);
467 }
468 
SetAsyncRevalidationRequested(bool requested)469 void WebURLResponse::SetAsyncRevalidationRequested(bool requested) {
470   resource_response_->SetAsyncRevalidationRequested(requested);
471 }
472 
SetNetworkAccessed(bool network_accessed)473 void WebURLResponse::SetNetworkAccessed(bool network_accessed) {
474   resource_response_->SetNetworkAccessed(network_accessed);
475 }
476 
FromArchive() const477 bool WebURLResponse::FromArchive() const {
478   return resource_response_->FromArchive();
479 }
480 
WebURLResponse(ResourceResponse & r)481 WebURLResponse::WebURLResponse(ResourceResponse& r) : resource_response_(&r) {}
482 
483 }  // namespace blink
484