Use references instead of pointers with ResourceLoadTiming.
[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.domainLookupStart < 0)
124         return fetchStart();
125
126     return resourceTimeToDocumentMilliseconds(m_timing.domainLookupStart);
127 }
128
129 double PerformanceResourceTiming::domainLookupEnd() const
130 {
131     if (!m_shouldReportDetails)
132         return 0.0;
133
134     if (m_timing.domainLookupEnd < 0)
135         return domainLookupStart();
136
137     return resourceTimeToDocumentMilliseconds(m_timing.domainLookupEnd);
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.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.domainLookupEnd >= 0)
152         connectStart = m_timing.domainLookupEnd;
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.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.secureConnectionStart < 0) // Secure connection not negotiated.
175         return 0.0;
176
177     return resourceTimeToDocumentMilliseconds(m_timing.secureConnectionStart);
178 }
179
180 double PerformanceResourceTiming::requestStart() const
181 {
182     if (!m_shouldReportDetails)
183         return 0.0;
184
185     return resourceTimeToDocumentMilliseconds(m_timing.requestStart);
186 }
187
188 double PerformanceResourceTiming::responseEnd() const
189 {
190     return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_finishTime);
191 }
192
193 double PerformanceResourceTiming::resourceTimeToDocumentMilliseconds(int deltaMilliseconds) const
194 {
195     if (!deltaMilliseconds)
196         return 0.0;
197     return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_requestingDocument.get()->loader()->timing()->navigationStart()) + deltaMilliseconds;
198 }
199
200 } // namespace WebCore
201
202 #endif // ENABLE(RESOURCE_TIMING)