Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1025)

Side by Side Diff: Source/core/timing/PerformanceObserver.cpp

Issue 1198863006: First version of PerformanceObserver (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Sync with latest spec draft (DOMString -> PerformanceEntryType and new PerformanceObserver -> windo… Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2015 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
esprehn 2015/07/18 22:24:16 short copyright
MikeB 2015/07/20 23:06:50 Done.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "core/timing/PerformanceObserver.h"
33
34 #include "bindings/core/v8/ExceptionState.h"
35 #include "core/dom/ExceptionCode.h"
36 #include "core/dom/Microtask.h"
37 #include "core/inspector/InspectorInstrumentation.h"
38 #include "core/timing/PerformanceBase.h"
39 #include "core/timing/PerformanceEntry.h"
40 #include "core/timing/PerformanceObserverCallback.h"
41 #include "core/timing/PerformanceObserverEntryList.h"
42 #include "core/timing/PerformanceObserverInit.h"
43 #include "core/timing/PerformanceObserverRegistration.h"
44 #include "wtf/MainThread.h"
45 #include <algorithm>
46
47 namespace blink {
48
49 static unsigned s_observerPriority = 0;
50
51 struct PerformanceObserver::ObserverLessThan {
52 bool operator()(const Member<PerformanceObserver>& lhs, const Member<Perform anceObserver>& rhs)
53 {
esprehn 2015/07/18 22:24:16 If you just use a ListHashSet you don't need this
MikeB 2015/07/20 23:06:50 Done.
54 return lhs->m_priority < rhs->m_priority;
55 }
56 };
57
58 PerformanceObserver* PerformanceObserver::create(PerformanceBase* performance, P erformanceObserverCallback* callback)
59 {
60 ASSERT(isMainThread());
61 return new PerformanceObserver(performance, callback);
62 }
63
64 PerformanceObserver::PerformanceObserver(PerformanceBase* performance, Performan ceObserverCallback* callback)
65 : m_callback(callback)
66 , m_performance(performance)
67 , m_priority(s_observerPriority++)
esprehn 2015/07/18 22:24:16 or this
MikeB 2015/07/20 23:06:50 Done.
68 {
69 }
70
71 PerformanceObserver::~PerformanceObserver()
72 {
73 if (!m_performanceEntries.isEmpty())
74 InspectorInstrumentation::didClearAllPerformanceObservations(m_callback- >executionContext(), this);
75 }
76
77 void PerformanceObserver::observe(const PerformanceObserverInit& observerInit, E xceptionState& exceptionState)
78 {
79 PerformanceBase* performance = m_performance.get();
80 if (!performance) {
81 exceptionState.throwTypeError("Window may be destroyed? Performance targ et is invalid.");
82 return;
83 }
84
85 HashSet<AtomicString> entryType;
86 if (observerInit.hasEntryType() && observerInit.entryType().size()) {
87 const Vector<String>& sequence = observerInit.entryType();
88 for (unsigned i = 0; i < sequence.size(); ++i)
89 entryType.add(AtomicString(sequence[i]));
90 } else {
91 exceptionState.throwTypeError("A Performance Observer MUST have a non-em pty typeFilter attribute.");
92 return;
93 }
94 for (auto registration : m_registrations) {
95 if (registration->performance() == performance) {
96 registration->resetObservation(entryType);
97 return;
98 }
99 }
100 PerformanceObserverRegistration::create(*this, performance, entryType);
101 }
102
103 void PerformanceObserver::disconnect()
104 {
105 m_performanceEntries.clear();
106 InspectorInstrumentation::didClearAllPerformanceObservations(m_callback->exe cutionContext(), this);
107 // registration->unregister() will call m_registrations.remove() and would
108 // invalidate the iterator being used here if we don't make a copy.
109 PerformanceObserverRegistrationSet copyOfRegistrations(m_registrations);
110 for (auto registration : copyOfRegistrations) {
111 registration->unregister();
112 }
113 }
114
115 void PerformanceObserver::observationStarted(PerformanceObserverRegistration* re gistration)
116 {
117 ASSERT(!m_registrations.contains(registration));
118 m_registrations.add(registration);
119 }
120
121 void PerformanceObserver::observationEnded(PerformanceObserverRegistration* regi stration)
122 {
123 ASSERT(m_registrations.contains(registration));
124 m_registrations.remove(m_registrations.find(registration));
125 }
126
127 static PerformanceObserverSet& activePerformanceObservers()
128 {
129 DEFINE_STATIC_LOCAL(Persistent<PerformanceObserverSet>, activeObservers, (ne w PerformanceObserverSet()));
130 return *activeObservers;
131 }
132
133 static PerformanceObserverSet& suspendedPerformanceObservers()
134 {
135 DEFINE_STATIC_LOCAL(Persistent<PerformanceObserverSet>, suspendedObservers, (new PerformanceObserverSet()));
136 return *suspendedObservers;
137 }
138
139 static void activateObserver(PerformanceObserver* observer)
140 {
141 if (activePerformanceObservers().isEmpty())
142 Microtask::enqueueMicrotask(WTF::bind(&PerformanceObserver::deliverObser vations));
143
144 activePerformanceObservers().add(observer);
145 }
146
147 void PerformanceObserver::enqueuePerformanceEntry(PerformanceEntry* entry)
148 {
149 ASSERT(isMainThread());
150 m_performanceEntries.append(entry);
151 activateObserver(this);
152 InspectorInstrumentation::didEnqueuePerformanceObserverEntries(m_callback->e xecutionContext(), this);
153 }
154
155 bool PerformanceObserver::shouldBeSuspended() const
156 {
157 return m_callback->executionContext() && m_callback->executionContext()->act iveDOMObjectsAreSuspended();
158 }
159
160 void PerformanceObserver::deliver()
161 {
162 ASSERT(!shouldBeSuspended());
163
164 if (m_performanceEntries.isEmpty())
165 return;
166
167 // TODO(mpb)
168 PerformanceEntryVector performanceEntries;
169 performanceEntries.swap(m_performanceEntries);
170 Member<PerformanceObserverEntryList> entryList(new PerformanceObserverEntryL ist(performanceEntries));
171
172 InspectorInstrumentation::willDeliverPerformanceObservations(m_callback->exe cutionContext(), this);
173 m_callback->handleEvent(entryList, this);
174 InspectorInstrumentation::didDeliverPerformanceObservations(m_callback->exec utionContext());
175 }
176
177 void PerformanceObserver::resumeSuspendedObservers()
178 {
179 ASSERT(isMainThread());
180 if (suspendedPerformanceObservers().isEmpty())
181 return;
182
183 PerformanceObserverVector suspended;
184 copyToVector(suspendedPerformanceObservers(), suspended);
185 for (size_t i = 0; i < suspended.size(); ++i) {
186 if (!suspended[i]->shouldBeSuspended()) {
187 suspendedPerformanceObservers().remove(suspended[i]);
188 activateObserver(suspended[i]);
189 }
190 }
191 }
192
193 void PerformanceObserver::deliverObservations()
194 {
195 ASSERT(isMainThread());
196 PerformanceObserverVector observers;
197 copyToVector(activePerformanceObservers(), observers);
198 activePerformanceObservers().clear();
199 std::sort(observers.begin(), observers.end(), ObserverLessThan());
200 for (size_t i = 0; i < observers.size(); ++i) {
201 if (observers[i]->shouldBeSuspended())
202 suspendedPerformanceObservers().add(observers[i]);
203 else
204 observers[i]->deliver();
205 }
206 }
207
208 DEFINE_TRACE(PerformanceObserver)
209 {
210 visitor->trace(m_callback);
211 visitor->trace(m_performance);
212 visitor->trace(m_performanceEntries);
213 visitor->trace(m_registrations);
214 }
215
216 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698