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 "core/page/PerformanceResourceTiming.h" 34 35 #include "core/dom/Document.h" 36 #include "core/loader/DocumentLoadTiming.h" 37 #include "core/loader/DocumentLoader.h" 38 #include "core/page/ResourceTimingInfo.h" 39 #include "core/platform/network/ResourceRequest.h" 40 #include "core/platform/network/ResourceResponse.h" 41 42 namespace WebCore { 43 44 static double monotonicTimeToDocumentMilliseconds(Document* document, double seconds) 45 { 46 ASSERT(seconds >= 0.0); 47 return document->loader()->timing()->monotonicTimeToZeroBasedDocumentTime(seconds) * 1000.0; 48 } 49 50 PerformanceResourceTiming::PerformanceResourceTiming(const ResourceTimingInfo& info, Document* requestingDocument, double startTime, double lastRedirectEndTime, bool allowTimingDetails, bool allowRedirectDetails) 51 : PerformanceEntry(info.initialRequest().url().string(), "resource", monotonicTimeToDocumentMilliseconds(requestingDocument, startTime), monotonicTimeToDocumentMilliseconds(requestingDocument, info.loadFinishTime())) 52 , m_initiatorType(info.initiatorType()) 53 , m_timing(info.finalResponse().resourceLoadTiming()) 54 , m_lastRedirectEndTime(lastRedirectEndTime) 55 , m_finishTime(info.loadFinishTime()) 56 , m_didReuseConnection(info.finalResponse().connectionReused()) 57 , m_allowTimingDetails(allowTimingDetails) 58 , m_allowRedirectDetails(allowRedirectDetails) 59 , m_requestingDocument(requestingDocument) 60 { 61 ScriptWrappable::init(this); 62 } 63 64 PerformanceResourceTiming::~PerformanceResourceTiming() 65 { 66 } 67 68 AtomicString PerformanceResourceTiming::initiatorType() const 69 { 70 return m_initiatorType; 71 } 72 73 double PerformanceResourceTiming::redirectStart() const 74 { 75 if (!m_lastRedirectEndTime || !m_allowRedirectDetails) 76 return 0.0; 77 78 return PerformanceEntry::startTime(); 79 } 80 81 double PerformanceResourceTiming::redirectEnd() const 82 { 83 if (!m_lastRedirectEndTime || !m_allowRedirectDetails) 84 return 0.0; 85 86 return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_lastRedirectEndTime); 87 } 88 89 double PerformanceResourceTiming::fetchStart() const 90 { 91 if (m_lastRedirectEndTime) { 92 // FIXME: ASSERT(m_timing) should be in constructor once timeticks of 93 // AppCache is exposed from chrome network stack, crbug/251100 94 ASSERT(m_timing); 95 return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_timing->requestTime); 96 } 97 98 return PerformanceEntry::startTime(); 99 } 100 101 double PerformanceResourceTiming::domainLookupStart() const 102 { 103 if (!m_allowTimingDetails) 104 return 0.0; 105 106 if (!m_timing || m_timing->dnsStart == 0.0) 107 return fetchStart(); 108 109 return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_timing->dnsStart); 110 } 111 112 double PerformanceResourceTiming::domainLookupEnd() const 113 { 114 if (!m_allowTimingDetails) 115 return 0.0; 116 117 if (!m_timing || m_timing->dnsEnd == 0.0) 118 return domainLookupStart(); 119 120 return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_timing->dnsEnd); 121 } 122 123 double PerformanceResourceTiming::connectStart() const 124 { 125 if (!m_allowTimingDetails) 126 return 0.0; 127 128 // connectStart will be zero when a network request is not made. 129 if (!m_timing || m_timing->connectStart == 0.0 || m_didReuseConnection) 130 return domainLookupEnd(); 131 132 // connectStart includes any DNS time, so we may need to trim that off. 133 double connectStart = m_timing->connectStart; 134 if (m_timing->dnsEnd > 0.0) 135 connectStart = m_timing->dnsEnd; 136 137 return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), connectStart); 138 } 139 140 double PerformanceResourceTiming::connectEnd() const 141 { 142 if (!m_allowTimingDetails) 143 return 0.0; 144 145 // connectStart will be zero when a network request is not made. 146 if (!m_timing || m_timing->connectEnd == 0.0 || m_didReuseConnection) 147 return connectStart(); 148 149 return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_timing->connectEnd); 150 } 151 152 double PerformanceResourceTiming::secureConnectionStart() const 153 { 154 if (!m_allowTimingDetails) 155 return 0.0; 156 157 if (!m_timing || m_timing->sslStart == 0.0) // Secure connection not negotiated. 158 return 0.0; 159 160 return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_timing->sslStart); 161 } 162 163 double PerformanceResourceTiming::requestStart() const 164 { 165 if (!m_allowTimingDetails) 166 return 0.0; 167 168 if (!m_timing) 169 return connectEnd(); 170 171 return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_timing->sendStart); 172 } 173 174 double PerformanceResourceTiming::responseStart() const 175 { 176 if (!m_allowTimingDetails) 177 return 0.0; 178 179 if (!m_timing) 180 return requestStart(); 181 182 // FIXME: This number isn't exactly correct. See the notes in PerformanceTiming::responseStart(). 183 return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_timing->receiveHeadersEnd); 184 } 185 186 double PerformanceResourceTiming::responseEnd() const 187 { 188 if (!m_finishTime) 189 return responseStart(); 190 191 return monotonicTimeToDocumentMilliseconds(m_requestingDocument.get(), m_finishTime); 192 } 193 194 } // namespace WebCore 195