Remove unsafe uses of AtomicallyInitializedStatic
[WebKit-https.git] / Source / WebCore / page / PerformanceResourceTiming.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  * Copyright (C) 2012 Intel 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 are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33 #include "PerformanceResourceTiming.h"
34
35 #if ENABLE(RESOURCE_TIMING)
36
37 #include "Document.h"
38 #include "DocumentLoadTiming.h"
39 #include "DocumentLoader.h"
40 #include "URL.h"
41 #include "ResourceRequest.h"
42 #include "ResourceResponse.h"
43 #include "SecurityOrigin.h"
44 #include <wtf/Vector.h>
45
46 namespace WebCore {
47
48 static double monotonicTimeToDocumentMilliseconds(Document* document, double seconds)
49 {
50     ASSERT(seconds >= 0.0);
51     return document->loader()->timing()->monotonicTimeToZeroBasedDocumentTime(seconds) * 1000.0;
52 }
53
54 static bool passesTimingAllowCheck(const ResourceResponse& response, Document* requestingDocument)
55 {
56     RefPtr<SecurityOrigin> resourceOrigin = SecurityOrigin::create(response.url());
57     if (resourceOrigin->isSameSchemeHostPort(requestingDocument->securityOrigin()))
58         return true;
59
60     const String& timingAllowOriginString = response.httpHeaderField("timing-allow-origin");
61     if (timingAllowOriginString.isEmpty() || equalIgnoringCase(timingAllowOriginString, "null"))
62         return false;
63
64     if (timingAllowOriginString == "*")
65         return true;
66
67     const String& securityOrigin = requestingDocument->securityOrigin()->toString();
68     Vector<String> timingAllowOrigins;
69     timingAllowOriginString.split(" ", timingAllowOrigins);
70     for (size_t i = 0; i < timingAllowOrigins.size(); ++i)
71         if (timingAllowOrigins[i] == securityOrigin)
72             return true;
73
74     return false;
75 }
76
77 PerformanceResourceTiming::PerformanceResourceTiming(const AtomicString& initiatorType, const ResourceRequest& request, const ResourceResponse& response, double initiationTime, double finishTime, Document* requestingDocument)
78     : PerformanceEntry(request.url().string(), "resource", monotonicTimeToDocumentMilliseconds(requestingDocument, initiationTime), monotonicTimeToDocumentMilliseconds(requestingDocument, finishTime))
79     , m_initiatorType(initiatorType)
80     , m_timing(response.resourceLoadTiming())
81     , m_finishTime(finishTime)
82     , m_didReuseConnection(response.connectionReused())
83     , m_shouldReportDetails(passesTimingAllowCheck(response, requestingDocument))
84     , m_requestingDocument(requestingDocument)
85 {
86 }
87
88 PerformanceResourceTiming::~PerformanceResourceTiming()
89 {
90 }
91
92 AtomicString PerformanceResourceTiming::initiatorType() const
93 {
94     return m_initiatorType;
95 }
96
97 double PerformanceResourceTiming::redirectStart() const
98 {
99     // FIXME: Need to track and report redirects for resources.
100     if (!m_shouldReportDetails)
101         return 0.0;
102     return 0;
103 }
104
105 double PerformanceResourceTiming::redirectEnd() const
106 {
107     if (!m_shouldReportDetails)
108         return 0.0;
109     return 0;
110 }
111
112 double PerformanceResourceTiming::fetchStart() const
113 {
114     // FIXME: This should be different depending on redirects.
115     return (startTime());
116 }
117
118 double PerformanceResourceTiming::domainLookupStart() const
119 {
120     if (!m_shouldReportDetails)
121         return 0.0;
122
123     if (!m_timing || m_timing->dnsStart < 0)
124         return fetchStart();
125
126     return resourceTimeToDocumentMilliseconds(m_timing->dnsStart);
127 }
128
129 double PerformanceResourceTiming::domainLookupEnd() const
130 {
131     if (!m_shouldReportDetails)
132         return 0.0;
133
134     if (!m_timing || m_timing->dnsEnd < 0)
135         return domainLookupStart();
136
137     return resourceTimeToDocumentMilliseconds(m_timing->dnsEnd);
138 }
139
140 double PerformanceResourceTiming::connectStart() const
141 {
142     if (!m_shouldReportDetails)
143         return 0.0;
144
145     // connectStart will be -1 when a network request is not made.
146     if (!m_timing || m_timing->connectStart < 0 || m_didReuseConnection)
147         return domainLookupEnd();
148
149     // connectStart includes any DNS time, so we may need to trim that off.
150     int connectStart = m_timing->connectStart;
151     if (m_timing->dnsEnd >= 0)
152         connectStart = m_timing->dnsEnd;
153
154     return resourceTimeToDocumentMilliseconds(connectStart);
155 }
156
157 double PerformanceResourceTiming::connectEnd() const
158 {
159     if (!m_shouldReportDetails)
160         return 0.0;
161
162     // connectStart will be -1 when a network request is not made.
163     if (!m_timing || m_timing->connectEnd < 0 || m_didReuseConnection)
164         return connectStart();
165
166     return resourceTimeToDocumentMilliseconds(m_timing->connectEnd);
167 }
168
169 double PerformanceResourceTiming::secureConnectionStart() const
170 {
171     if (!m_shouldReportDetails)
172         return 0.0;
173
174     if (!m_timing || m_timing->sslStart < 0) // Secure connection not negotiated.
175         return 0.0;
176
177     return resourceTimeToDocumentMilliseconds(m_timing->sslStart);
178 }
179
180 double PerformanceResourceTiming::requestStart() const
181 {
182     if (!m_shouldReportDetails)
183         return 0.0;
184
185     if (!m_timing)
186         return connectEnd();
187
188     return resourceTimeToDocumentMilliseconds(m_timing->sendStart);
189 }
190
191 double PerformanceResourceTiming::responseStart() const
192 {
193     if (!m_shouldReportDetails)
194         return 0.0;
195
196     if (!m_timing)
197         return requestStart();
198     // FIXME: This number isn't exactly correct. See the notes in PerformanceTiming::responseStart().
199     return resourceTimeToDocumentMilliseconds(m_timing->receiveHeadersEnd);
200 }
201
202 double PerformanceResourceTiming::responseEnd() const
203 {
204     if (!m_finishTime)
205         return responseStart();
206
207     return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_finishTime);
208 }
209
210 double PerformanceResourceTiming::resourceTimeToDocumentMilliseconds(int deltaMilliseconds) const
211 {
212     if (!deltaMilliseconds)
213         return 0.0;
214     return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_timing->requestTime) + deltaMilliseconds;
215 }
216
217 } // namespace WebCore
218
219 #endif // ENABLE(RESOURCE_TIMING)