2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * Copyright (C) 2012 Intel Inc. All rights reserved.
4 * Copyright (C) 2016 Apple Inc. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
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
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.
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.
34 #include "Performance.h"
36 #if ENABLE(WEB_TIMING)
39 #include "DocumentLoader.h"
40 #include "EventNames.h"
42 #include "PerformanceEntry.h"
43 #include "PerformanceNavigation.h"
44 #include "PerformanceObserver.h"
45 #include "PerformanceResourceTiming.h"
46 #include "PerformanceTiming.h"
47 #include "PerformanceUserTiming.h"
48 #include "ResourceResponse.h"
49 #include "ScriptExecutionContext.h"
50 #include <wtf/CurrentTime.h>
54 Performance::Performance(ScriptExecutionContext& context, double timeOrigin)
55 : ContextDestructionObserver(&context)
56 , m_timeOrigin(timeOrigin)
61 Performance::~Performance()
65 double Performance::now() const
67 double nowSeconds = monotonicallyIncreasingTime() - m_timeOrigin;
68 return 1000.0 * reduceTimeResolution(nowSeconds);
71 double Performance::reduceTimeResolution(double seconds)
73 const double resolutionSeconds = 0.0001;
74 return std::floor(seconds / resolutionSeconds) * resolutionSeconds;
77 PerformanceNavigation* Performance::navigation()
79 if (!is<Document>(scriptExecutionContext()))
82 ASSERT(isMainThread());
84 m_navigation = PerformanceNavigation::create(downcast<Document>(*scriptExecutionContext()).frame());
85 return m_navigation.get();
88 PerformanceTiming* Performance::timing()
90 if (!is<Document>(scriptExecutionContext()))
93 ASSERT(isMainThread());
95 m_timing = PerformanceTiming::create(downcast<Document>(*scriptExecutionContext()).frame());
96 return m_timing.get();
99 Vector<RefPtr<PerformanceEntry>> Performance::getEntries() const
101 Vector<RefPtr<PerformanceEntry>> entries;
103 entries.appendVector(m_resourceTimingBuffer);
106 entries.appendVector(m_userTiming->getMarks());
107 entries.appendVector(m_userTiming->getMeasures());
110 std::sort(entries.begin(), entries.end(), PerformanceEntry::startTimeCompareLessThan);
114 Vector<RefPtr<PerformanceEntry>> Performance::getEntriesByType(const String& entryType) const
116 Vector<RefPtr<PerformanceEntry>> entries;
118 if (equalLettersIgnoringASCIICase(entryType, "resource"))
119 entries.appendVector(m_resourceTimingBuffer);
122 if (equalLettersIgnoringASCIICase(entryType, "mark"))
123 entries.appendVector(m_userTiming->getMarks());
124 else if (equalLettersIgnoringASCIICase(entryType, "measure"))
125 entries.appendVector(m_userTiming->getMeasures());
128 std::sort(entries.begin(), entries.end(), PerformanceEntry::startTimeCompareLessThan);
132 Vector<RefPtr<PerformanceEntry>> Performance::getEntriesByName(const String& name, const String& entryType) const
134 Vector<RefPtr<PerformanceEntry>> entries;
136 if (entryType.isNull() || equalLettersIgnoringASCIICase(entryType, "resource")) {
137 for (auto& resource : m_resourceTimingBuffer) {
138 if (resource->name() == name)
139 entries.append(resource);
144 if (entryType.isNull() || equalLettersIgnoringASCIICase(entryType, "mark"))
145 entries.appendVector(m_userTiming->getMarks(name));
146 if (entryType.isNull() || equalLettersIgnoringASCIICase(entryType, "measure"))
147 entries.appendVector(m_userTiming->getMeasures(name));
150 std::sort(entries.begin(), entries.end(), PerformanceEntry::startTimeCompareLessThan);
154 void Performance::clearResourceTimings()
156 m_resourceTimingBuffer.clear();
159 void Performance::setResourceTimingBufferSize(unsigned size)
161 m_resourceTimingBufferSize = size;
163 if (isResourceTimingBufferFull())
164 dispatchEvent(Event::create(eventNames().resourcetimingbufferfullEvent, false, false));
167 void Performance::addResourceTiming(const String& initiatorName, const URL& originalURL, const ResourceResponse& response, const LoadTiming& loadTiming)
169 if (isResourceTimingBufferFull())
172 SecurityOrigin* securityOrigin = scriptExecutionContext()->securityOrigin();
176 RefPtr<PerformanceEntry> entry = PerformanceResourceTiming::create(initiatorName, originalURL, response, *securityOrigin, m_timeOrigin, loadTiming);
178 m_resourceTimingBuffer.append(entry);
180 if (isResourceTimingBufferFull())
181 dispatchEvent(Event::create(eventNames().resourcetimingbufferfullEvent, false, false));
184 bool Performance::isResourceTimingBufferFull() const
186 return m_resourceTimingBuffer.size() >= m_resourceTimingBufferSize;
189 ExceptionOr<void> Performance::mark(const String& markName)
192 m_userTiming = std::make_unique<UserTiming>(*this);
194 auto result = m_userTiming->mark(markName);
195 if (result.hasException())
196 return result.releaseException();
198 queueEntry(result.releaseReturnValue());
203 void Performance::clearMarks(const String& markName)
206 m_userTiming = std::make_unique<UserTiming>(*this);
207 m_userTiming->clearMarks(markName);
210 ExceptionOr<void> Performance::measure(const String& measureName, const String& startMark, const String& endMark)
213 m_userTiming = std::make_unique<UserTiming>(*this);
215 auto result = m_userTiming->measure(measureName, startMark, endMark);
216 if (result.hasException())
217 return result.releaseException();
219 queueEntry(result.releaseReturnValue());
224 void Performance::clearMeasures(const String& measureName)
227 m_userTiming = std::make_unique<UserTiming>(*this);
228 m_userTiming->clearMeasures(measureName);
231 void Performance::registerPerformanceObserver(PerformanceObserver& observer)
233 m_observers.add(&observer);
236 void Performance::unregisterPerformanceObserver(PerformanceObserver& observer)
238 m_observers.remove(&observer);
241 void Performance::queueEntry(PerformanceEntry& entry)
243 bool shouldScheduleTask = false;
244 for (auto& observer : m_observers) {
245 if (observer->typeFilter().contains(entry.type())) {
246 observer->queueEntry(entry);
247 shouldScheduleTask = true;
251 if (!shouldScheduleTask)
254 if (m_performanceTimelineTaskQueue.hasPendingTasks())
257 m_performanceTimelineTaskQueue.enqueueTask([this] () {
258 Vector<RefPtr<PerformanceObserver>> observers;
259 copyToVector(m_observers, observers);
260 for (auto& observer : observers)
265 } // namespace WebCore
267 #endif // ENABLE(WEB_TIMING)