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

Unified 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: Switch from microtask to timer for firing events. 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 side-by-side diff with in-line comments
Download patch
Index: Source/core/timing/PerformanceObserver.cpp
diff --git a/Source/core/timing/PerformanceObserver.cpp b/Source/core/timing/PerformanceObserver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1d22df1fd7f79ae770a39689375510f4756649dc
--- /dev/null
+++ b/Source/core/timing/PerformanceObserver.cpp
@@ -0,0 +1,181 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/timing/PerformanceObserver.h"
+
+#include "bindings/core/v8/ExceptionState.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/timing/PerformanceBase.h"
+#include "core/timing/PerformanceEntry.h"
+#include "core/timing/PerformanceObserverCallback.h"
+#include "core/timing/PerformanceObserverEntryList.h"
+#include "core/timing/PerformanceObserverInit.h"
+#include "platform/Timer.h"
+#include "wtf/MainThread.h"
+#include <algorithm>
+
+namespace blink {
+
+class BLINK_EXPORT PerformanceObserverTimerCoordinator {
+public:
+ PerformanceObserverTimerCoordinator();
+ ~PerformanceObserverTimerCoordinator() {}
+
+ void fired(Timer<PerformanceObserverTimerCoordinator>*);
+ PerformanceObserverSet& activePerformanceObservers() { return *m_activeObservers; }
+ PerformanceObserverSet& suspendedPerformanceObservers() { return *m_suspendedObservers; }
+private:
+ Persistent<PerformanceObserverSet> m_activeObservers;
+ Persistent<PerformanceObserverSet> m_suspendedObservers;
+};
+
+PerformanceObserverTimerCoordinator::PerformanceObserverTimerCoordinator()
+ : m_activeObservers(new PerformanceObserverSet())
+ , m_suspendedObservers(new PerformanceObserverSet())
+{
+}
+
+void PerformanceObserverTimerCoordinator::fired(Timer<PerformanceObserverTimerCoordinator>*)
+{
+ ASSERT(isMainThread());
+ PerformanceObserverVector observers;
+ copyToVector(activePerformanceObservers(), observers);
+ activePerformanceObservers().clear();
+ for (size_t i = 0; i < observers.size(); ++i) {
+ if (observers[i]->shouldBeSuspended())
+ suspendedPerformanceObservers().add(observers[i]);
+ else
+ observers[i]->deliver();
+ }
+}
+
+static PerformanceObserverTimerCoordinator& timerCoordinator()
+{
esprehn 2015/07/24 08:23:12 No static, PerformanceBase should own this. Each w
MikeB 2015/07/24 19:30:38 Done.
+ DEFINE_STATIC_LOCAL(PerformanceObserverTimerCoordinator*, coordinator, (new PerformanceObserverTimerCoordinator));
+ return *coordinator;
+}
+
+static Timer<PerformanceObserverTimerCoordinator>& deliverObservationsTimer()
+{
+ DEFINE_STATIC_LOCAL(Timer<PerformanceObserverTimerCoordinator>*, timer, (new Timer<PerformanceObserverTimerCoordinator>(&timerCoordinator(), &PerformanceObserverTimerCoordinator::fired)));
esprehn 2015/07/24 08:23:12 static Timer is usually bad, I think you want Perf
MikeB 2015/07/24 19:30:38 Done.
+ return *timer;
+}
+
+PerformanceObserver* PerformanceObserver::create(PerformanceBase* performance, PerformanceObserverCallback* callback)
+{
+ ASSERT(isMainThread());
+ return new PerformanceObserver(performance, callback);
+}
+
+PerformanceObserver::PerformanceObserver(PerformanceBase* performance, PerformanceObserverCallback* callback)
+ : m_callback(callback)
+ , m_performance(performance)
+ , m_filterOptions(PerformanceEntry::Invalid)
+ , m_isRegistered(false)
+{
+}
+
+PerformanceObserver::~PerformanceObserver()
+{
+ if (!m_performanceEntries.isEmpty())
+ InspectorInstrumentation::didClearAllPerformanceObservations(m_callback->executionContext(), this);
+}
+
+void PerformanceObserver::observe(const PerformanceObserverInit& observerInit, ExceptionState& exceptionState)
+{
+ if (!m_performance) {
+ exceptionState.throwTypeError("Window may be destroyed? Performance target is invalid.");
+ return;
+ }
+
+ PerformanceEntryType_t entryType = PerformanceEntry::Invalid;
+ if (observerInit.hasEntryType() && observerInit.entryType().size()) {
+ const Vector<String>& sequence = observerInit.entryType();
+ for (unsigned i = 0; i < sequence.size(); ++i)
+ entryType |= PerformanceEntry::toEntryTypeEnum(sequence[i]);
+ }
+ if (entryType == PerformanceEntry::Invalid) {
+ exceptionState.throwTypeError("A Performance Observer MUST have a non-empty entryType attribute.");
+ return;
+ }
+ if (m_isRegistered)
+ m_performance->unregisterPerformanceObserver(this);
+ m_filterOptions = entryType;
+ m_performance->registerPerformanceObserver(this);
+ m_isRegistered = true;
+}
+
+void PerformanceObserver::disconnect()
+{
+ m_performanceEntries.clear();
+ InspectorInstrumentation::didClearAllPerformanceObservations(m_callback->executionContext(), this);
+ if (m_performance)
+ m_performance->unregisterPerformanceObserver(this);
+ m_isRegistered = false;
+}
+
+static void activateObserver(PerformanceObserver* observer)
+{
+ if (timerCoordinator().activePerformanceObservers().isEmpty())
+ deliverObservationsTimer().startOneShot(0, FROM_HERE);
+
+ timerCoordinator().activePerformanceObservers().add(observer);
+}
+
+void PerformanceObserver::enqueuePerformanceEntry(PerformanceEntry* entry)
+{
+ ASSERT(isMainThread());
+ m_performanceEntries.append(entry);
+ activateObserver(this);
+ InspectorInstrumentation::didEnqueuePerformanceObserverEntries(m_callback->executionContext(), this);
+}
+
+bool PerformanceObserver::shouldBeSuspended() const
+{
+ return m_callback->executionContext() && m_callback->executionContext()->activeDOMObjectsAreSuspended();
+}
+
+void PerformanceObserver::deliver()
+{
+ ASSERT(!shouldBeSuspended());
+
+ if (m_performanceEntries.isEmpty())
+ return;
+
+ PerformanceEntryVector performanceEntries;
+ performanceEntries.swap(m_performanceEntries);
+ Member<PerformanceObserverEntryList> entryList(new PerformanceObserverEntryList(performanceEntries));
+
+ InspectorInstrumentation::willDeliverPerformanceObservations(m_callback->executionContext(), this);
+ m_callback->handleEvent(entryList, this);
+ InspectorInstrumentation::didDeliverPerformanceObservations(m_callback->executionContext());
+}
+
+void PerformanceObserver::resumeSuspendedObservers()
+{
+ ASSERT(isMainThread());
+ if (timerCoordinator().suspendedPerformanceObservers().isEmpty())
+ return;
+
+ PerformanceObserverVector suspended;
+ copyToVector(timerCoordinator().suspendedPerformanceObservers(), suspended);
+ for (size_t i = 0; i < suspended.size(); ++i) {
+ if (!suspended[i]->shouldBeSuspended()) {
+ timerCoordinator().suspendedPerformanceObservers().remove(suspended[i]);
+ activateObserver(suspended[i]);
+ }
+ }
+}
+
+
+DEFINE_TRACE(PerformanceObserver)
+{
+ visitor->trace(m_callback);
+ visitor->trace(m_performance);
+ visitor->trace(m_performanceEntries);
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698