03c18b6927a2d4060e98f4d23f1db52841d275ae
[WebKit-https.git] / Source / WebCore / platform / network / NetworkLoadMetrics.h
1 /*
2  * Copyright (C) 2010 Google, Inc. All Rights Reserved.
3  * Copyright (C) 2014-2017 Apple, 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. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #pragma once
28
29 #include "HTTPHeaderMap.h"
30 #include <wtf/Optional.h>
31 #include <wtf/Seconds.h>
32 #include <wtf/persistence/PersistentDecoder.h>
33 #include <wtf/persistence/PersistentEncoder.h>
34 #include <wtf/text/WTFString.h>
35
36 #if PLATFORM(COCOA)
37 OBJC_CLASS NSDictionary;
38 #endif
39
40 namespace WebCore {
41
42 enum class NetworkLoadPriority : uint8_t {
43     Low,
44     Medium,
45     High,
46     Unknown,
47 };
48
49 class NetworkLoadMetrics {
50 public:
51     NetworkLoadMetrics()
52     {
53         reset();
54     }
55
56     NetworkLoadMetrics isolatedCopy() const
57     {
58         NetworkLoadMetrics copy;
59
60         copy.domainLookupStart = domainLookupStart;
61         copy.domainLookupEnd = domainLookupEnd;
62         copy.connectStart = connectStart;
63         copy.secureConnectionStart = secureConnectionStart;
64         copy.connectEnd = connectEnd;
65         copy.requestStart = requestStart;
66         copy.responseStart = responseStart;
67         copy.responseEnd = responseEnd;
68         copy.complete = complete;
69         copy.protocol = protocol.isolatedCopy();
70
71         copy.remoteAddress = remoteAddress.isolatedCopy();
72         copy.connectionIdentifier = connectionIdentifier.isolatedCopy();
73         copy.priority = priority;
74         copy.tlsProtocol = tlsProtocol.isolatedCopy();
75         copy.tlsCipher = tlsCipher.isolatedCopy();
76         copy.requestHeaders = requestHeaders.isolatedCopy();
77
78         copy.requestHeaderBytesSent = requestHeaderBytesSent;
79         copy.requestBodyBytesSent = requestBodyBytesSent;
80         copy.responseHeaderBytesReceived = responseHeaderBytesReceived;
81         copy.responseBodyBytesReceived = responseBodyBytesReceived;
82         copy.responseBodyDecodedSize = responseBodyDecodedSize;
83
84         return copy;
85     }
86
87     void reset()
88     {
89         domainLookupStart = Seconds(-1);
90         domainLookupEnd = Seconds(-1);
91         connectStart = Seconds(-1);
92         secureConnectionStart = Seconds(-1);
93         connectEnd = Seconds(-1);
94         requestStart = Seconds(0);
95         responseStart = Seconds(0);
96         responseEnd = Seconds(0);
97         complete = false;
98         protocol = String();
99         clearNonTimingData();
100     }
101
102     void clearNonTimingData()
103     {
104         remoteAddress = String();
105         connectionIdentifier = String();
106         priority = NetworkLoadPriority::Unknown;
107         tlsProtocol = String();
108         tlsCipher = String();
109         requestHeaders.clear();
110         requestHeaderBytesSent = std::numeric_limits<uint32_t>::max();
111         requestBodyBytesSent = std::numeric_limits<uint64_t>::max();
112         responseHeaderBytesReceived = std::numeric_limits<uint32_t>::max();
113         responseBodyBytesReceived = std::numeric_limits<uint64_t>::max();
114         responseBodyDecodedSize = std::numeric_limits<uint64_t>::max();
115     }
116
117     bool operator==(const NetworkLoadMetrics& other) const
118     {
119         return domainLookupStart == other.domainLookupStart
120             && domainLookupEnd == other.domainLookupEnd
121             && connectStart == other.connectStart
122             && secureConnectionStart == other.secureConnectionStart
123             && connectEnd == other.connectEnd
124             && requestStart == other.requestStart
125             && responseStart == other.responseStart
126             && responseEnd == other.responseEnd
127             && complete == other.complete
128             && protocol == other.protocol
129             && remoteAddress == other.remoteAddress
130             && connectionIdentifier == other.connectionIdentifier
131             && priority == other.priority
132             && tlsProtocol == other.tlsProtocol
133             && tlsCipher == other.tlsCipher
134             && requestHeaders == other.requestHeaders
135             && requestHeaderBytesSent == other.requestHeaderBytesSent
136             && requestBodyBytesSent == other.requestBodyBytesSent
137             && responseHeaderBytesReceived == other.responseHeaderBytesReceived
138             && responseBodyBytesReceived == other.responseBodyBytesReceived
139             && responseBodyDecodedSize == other.responseBodyDecodedSize;
140     }
141
142     bool operator!=(const NetworkLoadMetrics& other) const
143     {
144         return !(*this == other);
145     }
146
147     bool isComplete() const { return complete; }
148     void markComplete() { complete = true; }
149
150     template<class Encoder> void encode(Encoder&) const;
151     template<class Decoder> static bool decode(Decoder&, NetworkLoadMetrics&);
152
153     // These should be treated as deltas to LoadTiming's fetchStart.
154     // They should be in ascending order as listed here.
155     Seconds domainLookupStart;     // -1 if no DNS.
156     Seconds domainLookupEnd;       // -1 if no DNS.
157     Seconds connectStart;          // -1 if reused connection.
158     Seconds secureConnectionStart; // -1 if no secure connection.
159     Seconds connectEnd;            // -1 if reused connection.
160     Seconds requestStart;
161     Seconds responseStart;
162     Seconds responseEnd;
163
164     // ALPN Protocol ID: https://w3c.github.io/resource-timing/#bib-RFC7301
165     String protocol;
166
167     String remoteAddress;
168     String connectionIdentifier;
169     NetworkLoadPriority priority;
170
171     String tlsProtocol;
172     String tlsCipher;
173
174     // Whether or not all of the properties (0 or otherwise) have been set.
175     bool complete { false };
176
177     HTTPHeaderMap requestHeaders;
178
179     uint64_t requestHeaderBytesSent;
180     uint64_t responseHeaderBytesReceived;
181     uint64_t requestBodyBytesSent;
182     uint64_t responseBodyBytesReceived;
183     uint64_t responseBodyDecodedSize;
184 };
185
186 #if PLATFORM(COCOA)
187 WEBCORE_EXPORT void copyTimingData(NSDictionary *timingData, NetworkLoadMetrics&);
188 #endif
189
190 #if PLATFORM(COCOA) && !HAVE(TIMINGDATAOPTIONS)
191 WEBCORE_EXPORT void setCollectsTimingData();
192 #endif
193
194 template<class Encoder>
195 void NetworkLoadMetrics::encode(Encoder& encoder) const
196 {
197     encoder << domainLookupStart;
198     encoder << domainLookupEnd;
199     encoder << connectStart;
200     encoder << secureConnectionStart;
201     encoder << connectEnd;
202     encoder << requestStart;
203     encoder << responseStart;
204     encoder << responseEnd;
205     encoder << complete;
206     encoder << protocol;
207     encoder << remoteAddress;
208     encoder << connectionIdentifier;
209     encoder << priority;
210     encoder << tlsProtocol;
211     encoder << tlsCipher;
212     encoder << requestHeaders;
213     encoder << requestHeaderBytesSent;
214     encoder << requestBodyBytesSent;
215     encoder << responseHeaderBytesReceived;
216     encoder << responseBodyBytesReceived;
217     encoder << responseBodyDecodedSize;
218 }
219
220 template<class Decoder>
221 bool NetworkLoadMetrics::decode(Decoder& decoder, NetworkLoadMetrics& metrics)
222 {
223     return decoder.decode(metrics.domainLookupStart)
224         && decoder.decode(metrics.domainLookupEnd)
225         && decoder.decode(metrics.connectStart)
226         && decoder.decode(metrics.secureConnectionStart)
227         && decoder.decode(metrics.connectEnd)
228         && decoder.decode(metrics.requestStart)
229         && decoder.decode(metrics.responseStart)
230         && decoder.decode(metrics.responseEnd)
231         && decoder.decode(metrics.complete)
232         && decoder.decode(metrics.protocol)
233         && decoder.decode(metrics.remoteAddress)
234         && decoder.decode(metrics.connectionIdentifier)
235         && decoder.decode(metrics.priority)
236         && decoder.decode(metrics.tlsProtocol)
237         && decoder.decode(metrics.tlsCipher)
238         && decoder.decode(metrics.requestHeaders)
239         && decoder.decode(metrics.requestHeaderBytesSent)
240         && decoder.decode(metrics.requestBodyBytesSent)
241         && decoder.decode(metrics.responseHeaderBytesReceived)
242         && decoder.decode(metrics.responseBodyBytesReceived)
243         && decoder.decode(metrics.responseBodyDecodedSize);
244 }
245
246 } // namespace WebCore
247
248 // NetworkLoadMetrics should not be stored by the WTF::Persistence::Decoder.
249 namespace WTF {
250 namespace Persistence {
251
252 template<> struct Coder<Optional<WebCore::NetworkLoadPriority>> {
253     static NO_RETURN_DUE_TO_ASSERT void encode(Encoder&, const Optional<WebCore::NetworkLoadPriority>&)
254     {
255         ASSERT_NOT_REACHED();
256     }
257
258     static bool decode(Decoder&, Optional<WebCore::NetworkLoadPriority>&)
259     {
260         ASSERT_NOT_REACHED();
261         return false;
262     }
263 };
264
265 }} // namespace WTF::Persistence