[WTF] Add user-defined literal for ASCIILiteral
[WebKit-https.git] / Source / WebCore / page / PerformanceResourceTiming.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Google Inc. All rights reserved.
4  * Copyright (C) 2012 Intel 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 are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation and/or other materials provided with the
15  * distribution.
16  *     * Neither the name of Google Inc. nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "config.h"
34 #include "PerformanceResourceTiming.h"
35
36 #include "Document.h"
37 #include "DocumentLoader.h"
38 #include "LoadTiming.h"
39 #include "ResourceResponse.h"
40 #include "ResourceTiming.h"
41 #include "URL.h"
42
43 namespace WebCore {
44
45 static double monotonicTimeToDOMHighResTimeStamp(MonotonicTime timeOrigin, MonotonicTime timeStamp)
46 {
47     ASSERT(timeStamp.secondsSinceEpoch().seconds() >= 0);
48     if (!timeStamp || !timeOrigin)
49         return 0;
50
51     Seconds seconds = timeStamp - timeOrigin;
52     return Performance::reduceTimeResolution(seconds).milliseconds();
53 }
54
55 static double entryStartTime(MonotonicTime timeOrigin, const ResourceTiming& resourceTiming)
56 {
57     return monotonicTimeToDOMHighResTimeStamp(timeOrigin, resourceTiming.loadTiming().startTime());
58 }
59
60 static double entryEndTime(MonotonicTime timeOrigin, const ResourceTiming& resourceTiming)
61 {
62     if (resourceTiming.networkLoadMetrics().isComplete()) {
63         Seconds endTime = (resourceTiming.loadTiming().fetchStart() + resourceTiming.networkLoadMetrics().responseEnd) - timeOrigin;
64         return Performance::reduceTimeResolution(endTime).milliseconds();
65     }
66
67     return monotonicTimeToDOMHighResTimeStamp(timeOrigin, resourceTiming.loadTiming().responseEnd());
68 }
69
70 Ref<PerformanceResourceTiming> PerformanceResourceTiming::create(MonotonicTime timeOrigin, ResourceTiming&& resourceTiming)
71 {
72     return adoptRef(*new PerformanceResourceTiming(timeOrigin, WTFMove(resourceTiming)));
73 }
74
75 PerformanceResourceTiming::PerformanceResourceTiming(MonotonicTime timeOrigin, ResourceTiming&& resourceTiming)
76     : PerformanceEntry(PerformanceEntry::Type::Resource, resourceTiming.url().string(), "resource"_s, entryStartTime(timeOrigin, resourceTiming), entryEndTime(timeOrigin, resourceTiming))
77     , m_initiatorType(resourceTiming.initiator())
78     , m_timeOrigin(timeOrigin)
79     , m_loadTiming(resourceTiming.loadTiming())
80     , m_networkLoadMetrics(resourceTiming.networkLoadMetrics())
81     , m_shouldReportDetails(resourceTiming.allowTimingDetails())
82     , m_serverTiming(resourceTiming.populateServerTiming())
83 {
84     m_networkLoadMetrics.clearNonTimingData();
85 }
86
87 PerformanceResourceTiming::~PerformanceResourceTiming() = default;
88
89 String PerformanceResourceTiming::nextHopProtocol() const
90 {
91     return m_networkLoadMetrics.protocol;
92 }
93
94 double PerformanceResourceTiming::workerStart() const
95 {
96     // FIXME: <https://webkit.org/b/179377> Implement PerformanceResourceTiming.workerStart in ServiceWorkers
97     return 0.0;
98 }
99
100 double PerformanceResourceTiming::redirectStart() const
101 {
102     if (!m_shouldReportDetails)
103         return 0.0;
104
105     return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_loadTiming.redirectStart());
106 }
107
108 double PerformanceResourceTiming::redirectEnd() const
109 {
110     if (!m_shouldReportDetails)
111         return 0.0;
112
113     return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_loadTiming.redirectEnd());
114 }
115
116 double PerformanceResourceTiming::fetchStart() const
117 {
118     // fetchStart is a required property.
119     ASSERT(m_loadTiming.fetchStart());
120
121     return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_loadTiming.fetchStart());
122 }
123
124 double PerformanceResourceTiming::domainLookupStart() const
125 {
126     if (!m_shouldReportDetails)
127         return 0.0;
128
129     if (m_networkLoadMetrics.domainLookupStart <= 0_ms)
130         return fetchStart();
131
132     return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.domainLookupStart);
133 }
134
135 double PerformanceResourceTiming::domainLookupEnd() const
136 {
137     if (!m_shouldReportDetails)
138         return 0.0;
139
140     if (m_networkLoadMetrics.domainLookupEnd <= 0_ms)
141         return domainLookupStart();
142
143     return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.domainLookupEnd);
144 }
145
146 double PerformanceResourceTiming::connectStart() const
147 {
148     if (!m_shouldReportDetails)
149         return 0.0;
150
151     if (m_networkLoadMetrics.connectStart <= 0_ms)
152         return domainLookupEnd();
153
154     return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.connectStart);
155 }
156
157 double PerformanceResourceTiming::connectEnd() const
158 {
159     if (!m_shouldReportDetails)
160         return 0.0;
161
162     if (m_networkLoadMetrics.connectEnd <= 0_ms)
163         return connectStart();
164
165     return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.connectEnd);
166 }
167
168 double PerformanceResourceTiming::secureConnectionStart() const
169 {
170     if (!m_shouldReportDetails)
171         return 0.0;
172
173     if (m_networkLoadMetrics.secureConnectionStart <= 0_ms)
174         return 0.0;
175
176     return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.secureConnectionStart);
177 }
178
179 double PerformanceResourceTiming::requestStart() const
180 {
181     if (!m_shouldReportDetails)
182         return 0.0;
183
184     // requestStart is 0 when a network request is not made.
185     if (m_networkLoadMetrics.requestStart <= 0_ms)
186         return connectEnd();
187
188     return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.requestStart);
189 }
190
191 double PerformanceResourceTiming::responseStart() const
192 {
193     if (!m_shouldReportDetails)
194         return 0.0;
195
196     // responseStart is 0 when a network request is not made.
197     if (m_networkLoadMetrics.responseStart <= 0_ms)
198         return requestStart();
199
200     return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.responseStart);
201 }
202
203 double PerformanceResourceTiming::responseEnd() const
204 {
205     // responseEnd is a required property.
206     ASSERT(m_networkLoadMetrics.isComplete() || m_loadTiming.responseEnd());
207
208     if (m_networkLoadMetrics.isComplete()) {
209         // responseEnd is 0 when a network request is not made.
210         // This should mean all other properties are empty.
211         if (m_networkLoadMetrics.responseEnd <= 0_ms) {
212             ASSERT(m_networkLoadMetrics.responseStart <= 0_ms);
213             ASSERT(m_networkLoadMetrics.requestStart <= 0_ms);
214             ASSERT(m_networkLoadMetrics.requestStart <= 0_ms);
215             ASSERT(m_networkLoadMetrics.secureConnectionStart <= 0_ms);
216             ASSERT(m_networkLoadMetrics.connectEnd <= 0_ms);
217             ASSERT(m_networkLoadMetrics.connectStart <= 0_ms);
218             ASSERT(m_networkLoadMetrics.domainLookupEnd <= 0_ms);
219             ASSERT(m_networkLoadMetrics.domainLookupStart <= 0_ms);
220             return fetchStart();
221         }
222
223         return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.responseEnd);
224     }
225
226     return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_loadTiming.responseEnd());
227 }
228
229 double PerformanceResourceTiming::networkLoadTimeToDOMHighResTimeStamp(Seconds delta) const
230 {
231     ASSERT(delta);
232     Seconds final = (m_loadTiming.fetchStart() + delta) - m_timeOrigin;
233     return Performance::reduceTimeResolution(final).milliseconds();
234 }
235
236 } // namespace WebCore