2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * Copyright (C) 2012 Intel Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
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
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.
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.
33 #include "core/timing/Performance.h"
35 #include "core/dom/Document.h"
36 #include "core/frame/LocalFrame.h"
37 #include "core/loader/DocumentLoader.h"
38 #include "core/timing/ResourceTimingInfo.h"
39 #include "core/timing/PerformanceResourceTiming.h"
40 #include "core/timing/PerformanceUserTiming.h"
41 #include "platform/weborigin/SecurityOrigin.h"
42 #include "wtf/CurrentTime.h"
46 static const size_t defaultResourceTimingBufferSize = 150;
48 Performance::Performance(LocalFrame* frame)
49 : DOMWindowProperty(frame)
50 , m_resourceTimingBufferSize(defaultResourceTimingBufferSize)
51 , m_referenceTime(frame && frame->host() ? frame->document()->loader()->timing()->referenceMonotonicTime() : 0.0)
52 , m_userTiming(nullptr)
56 Performance::~Performance()
60 const AtomicString& Performance::interfaceName() const
62 return EventTargetNames::Performance;
65 ExecutionContext* Performance::executionContext() const
69 return frame()->document();
72 PassRefPtrWillBeRawPtr<MemoryInfo> Performance::memory() const
74 return MemoryInfo::create();
77 PerformanceNavigation* Performance::navigation() const
80 m_navigation = PerformanceNavigation::create(m_frame);
82 return m_navigation.get();
85 PerformanceTiming* Performance::timing() const
88 m_timing = PerformanceTiming::create(m_frame);
90 return m_timing.get();
93 PerformanceEntryVector Performance::getEntries() const
95 PerformanceEntryVector entries;
97 entries.appendVector(m_resourceTimingBuffer);
100 entries.appendVector(m_userTiming->getMarks());
101 entries.appendVector(m_userTiming->getMeasures());
104 std::sort(entries.begin(), entries.end(), PerformanceEntry::startTimeCompareLessThan);
108 PerformanceEntryVector Performance::getEntriesByType(const String& entryType)
110 PerformanceEntryVector entries;
112 if (equalIgnoringCase(entryType, "resource")) {
113 for (const auto& resource : m_resourceTimingBuffer)
114 entries.append(resource);
118 if (equalIgnoringCase(entryType, "mark"))
119 entries.appendVector(m_userTiming->getMarks());
120 else if (equalIgnoringCase(entryType, "measure"))
121 entries.appendVector(m_userTiming->getMeasures());
124 std::sort(entries.begin(), entries.end(), PerformanceEntry::startTimeCompareLessThan);
128 PerformanceEntryVector Performance::getEntriesByName(const String& name, const String& entryType)
130 PerformanceEntryVector entries;
132 if (entryType.isNull() || equalIgnoringCase(entryType, "resource")) {
133 for (const auto& resource : m_resourceTimingBuffer) {
134 if (resource->name() == name)
135 entries.append(resource);
140 if (entryType.isNull() || equalIgnoringCase(entryType, "mark"))
141 entries.appendVector(m_userTiming->getMarks(name));
142 if (entryType.isNull() || equalIgnoringCase(entryType, "measure"))
143 entries.appendVector(m_userTiming->getMeasures(name));
146 std::sort(entries.begin(), entries.end(), PerformanceEntry::startTimeCompareLessThan);
150 void Performance::webkitClearResourceTimings()
152 m_resourceTimingBuffer.clear();
155 void Performance::webkitSetResourceTimingBufferSize(unsigned size)
157 m_resourceTimingBufferSize = size;
158 if (isResourceTimingBufferFull())
159 dispatchEvent(Event::create(EventTypeNames::webkitresourcetimingbufferfull));
162 static bool passesTimingAllowCheck(const ResourceResponse& response, Document* requestingDocument, const AtomicString& originalTimingAllowOrigin)
164 AtomicallyInitializedStatic(AtomicString&, timingAllowOrigin = *new AtomicString("timing-allow-origin"));
166 RefPtr<SecurityOrigin> resourceOrigin = SecurityOrigin::create(response.url());
167 if (resourceOrigin->isSameSchemeHostPort(requestingDocument->securityOrigin()))
170 const AtomicString& timingAllowOriginString = originalTimingAllowOrigin.isEmpty() ? response.httpHeaderField(timingAllowOrigin) : originalTimingAllowOrigin;
171 if (timingAllowOriginString.isEmpty() || equalIgnoringCase(timingAllowOriginString, "null"))
174 if (timingAllowOriginString == starAtom)
177 const String& securityOrigin = requestingDocument->securityOrigin()->toString();
178 Vector<String> timingAllowOrigins;
179 timingAllowOriginString.string().split(' ', timingAllowOrigins);
180 for (const String& allowOrigin : timingAllowOrigins) {
181 if (allowOrigin == securityOrigin)
188 static bool allowsTimingRedirect(const Vector<ResourceResponse>& redirectChain, const ResourceResponse& finalResponse, Document* initiatorDocument)
190 if (!passesTimingAllowCheck(finalResponse, initiatorDocument, emptyAtom))
193 for (const ResourceResponse& response : redirectChain) {
194 if (!passesTimingAllowCheck(response, initiatorDocument, emptyAtom))
201 void Performance::addResourceTiming(const ResourceTimingInfo& info, Document* initiatorDocument)
203 if (isResourceTimingBufferFull())
206 const ResourceResponse& finalResponse = info.finalResponse();
207 bool allowTimingDetails = passesTimingAllowCheck(finalResponse, initiatorDocument, info.originalTimingAllowOrigin());
208 double startTime = info.initialTime();
210 if (info.redirectChain().isEmpty()) {
211 RefPtrWillBeRawPtr<PerformanceEntry> entry = PerformanceResourceTiming::create(info, initiatorDocument, startTime, allowTimingDetails);
212 addResourceTimingBuffer(entry);
216 const Vector<ResourceResponse>& redirectChain = info.redirectChain();
217 bool allowRedirectDetails = allowsTimingRedirect(redirectChain, finalResponse, initiatorDocument);
219 if (!allowRedirectDetails) {
220 ResourceLoadTiming* finalTiming = finalResponse.resourceLoadTiming();
223 startTime = finalTiming->requestTime;
226 ResourceLoadTiming* lastRedirectTiming = redirectChain.last().resourceLoadTiming();
227 ASSERT(lastRedirectTiming);
228 double lastRedirectEndTime = lastRedirectTiming->receiveHeadersEnd;
230 RefPtrWillBeRawPtr<PerformanceEntry> entry = PerformanceResourceTiming::create(info, initiatorDocument, startTime, lastRedirectEndTime, allowTimingDetails, allowRedirectDetails);
231 addResourceTimingBuffer(entry);
234 void Performance::addResourceTimingBuffer(PassRefPtrWillBeRawPtr<PerformanceEntry> entry)
236 m_resourceTimingBuffer.append(entry);
238 if (isResourceTimingBufferFull())
239 dispatchEvent(Event::create(EventTypeNames::webkitresourcetimingbufferfull));
242 bool Performance::isResourceTimingBufferFull()
244 return m_resourceTimingBuffer.size() >= m_resourceTimingBufferSize;
247 void Performance::mark(const String& markName, ExceptionState& exceptionState)
250 m_userTiming = UserTiming::create(this);
251 m_userTiming->mark(markName, exceptionState);
254 void Performance::clearMarks(const String& markName)
257 m_userTiming = UserTiming::create(this);
258 m_userTiming->clearMarks(markName);
261 void Performance::measure(const String& measureName, const String& startMark, const String& endMark, ExceptionState& exceptionState)
264 m_userTiming = UserTiming::create(this);
265 m_userTiming->measure(measureName, startMark, endMark, exceptionState);
268 void Performance::clearMeasures(const String& measureName)
271 m_userTiming = UserTiming::create(this);
272 m_userTiming->clearMeasures(measureName);
275 double Performance::now() const
277 return 1000.0 * (monotonicallyIncreasingTime() - m_referenceTime);
280 void Performance::trace(Visitor* visitor)
282 visitor->trace(m_navigation);
283 visitor->trace(m_timing);
284 visitor->trace(m_resourceTimingBuffer);
285 visitor->trace(m_userTiming);
286 EventTargetWithInlineData::trace(visitor);
287 DOMWindowProperty::trace(visitor);