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

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: 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 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..9f03a254e75c39e8bb2bd809de531d59518972ce
--- /dev/null
+++ b/Source/core/timing/PerformanceObserver.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2015 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
esprehn 2015/07/18 22:24:16 short copyright
MikeB 2015/07/20 23:06:50 Done.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/timing/PerformanceObserver.h"
+
+#include "bindings/core/v8/ExceptionState.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/Microtask.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 "core/timing/PerformanceObserverRegistration.h"
+#include "wtf/MainThread.h"
+#include <algorithm>
+
+namespace blink {
+
+static unsigned s_observerPriority = 0;
+
+struct PerformanceObserver::ObserverLessThan {
+ bool operator()(const Member<PerformanceObserver>& lhs, const Member<PerformanceObserver>& rhs)
+ {
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.
+ return lhs->m_priority < rhs->m_priority;
+ }
+};
+
+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_priority(s_observerPriority++)
esprehn 2015/07/18 22:24:16 or this
MikeB 2015/07/20 23:06:50 Done.
+{
+}
+
+PerformanceObserver::~PerformanceObserver()
+{
+ if (!m_performanceEntries.isEmpty())
+ InspectorInstrumentation::didClearAllPerformanceObservations(m_callback->executionContext(), this);
+}
+
+void PerformanceObserver::observe(const PerformanceObserverInit& observerInit, ExceptionState& exceptionState)
+{
+ PerformanceBase* performance = m_performance.get();
+ if (!performance) {
+ exceptionState.throwTypeError("Window may be destroyed? Performance target is invalid.");
+ return;
+ }
+
+ HashSet<AtomicString> entryType;
+ if (observerInit.hasEntryType() && observerInit.entryType().size()) {
+ const Vector<String>& sequence = observerInit.entryType();
+ for (unsigned i = 0; i < sequence.size(); ++i)
+ entryType.add(AtomicString(sequence[i]));
+ } else {
+ exceptionState.throwTypeError("A Performance Observer MUST have a non-empty typeFilter attribute.");
+ return;
+ }
+ for (auto registration : m_registrations) {
+ if (registration->performance() == performance) {
+ registration->resetObservation(entryType);
+ return;
+ }
+ }
+ PerformanceObserverRegistration::create(*this, performance, entryType);
+}
+
+void PerformanceObserver::disconnect()
+{
+ m_performanceEntries.clear();
+ InspectorInstrumentation::didClearAllPerformanceObservations(m_callback->executionContext(), this);
+ // registration->unregister() will call m_registrations.remove() and would
+ // invalidate the iterator being used here if we don't make a copy.
+ PerformanceObserverRegistrationSet copyOfRegistrations(m_registrations);
+ for (auto registration : copyOfRegistrations) {
+ registration->unregister();
+ }
+}
+
+void PerformanceObserver::observationStarted(PerformanceObserverRegistration* registration)
+{
+ ASSERT(!m_registrations.contains(registration));
+ m_registrations.add(registration);
+}
+
+void PerformanceObserver::observationEnded(PerformanceObserverRegistration* registration)
+{
+ ASSERT(m_registrations.contains(registration));
+ m_registrations.remove(m_registrations.find(registration));
+}
+
+static PerformanceObserverSet& activePerformanceObservers()
+{
+ DEFINE_STATIC_LOCAL(Persistent<PerformanceObserverSet>, activeObservers, (new PerformanceObserverSet()));
+ return *activeObservers;
+}
+
+static PerformanceObserverSet& suspendedPerformanceObservers()
+{
+ DEFINE_STATIC_LOCAL(Persistent<PerformanceObserverSet>, suspendedObservers, (new PerformanceObserverSet()));
+ return *suspendedObservers;
+}
+
+static void activateObserver(PerformanceObserver* observer)
+{
+ if (activePerformanceObservers().isEmpty())
+ Microtask::enqueueMicrotask(WTF::bind(&PerformanceObserver::deliverObservations));
+
+ 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;
+
+ // TODO(mpb)
+ 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 (suspendedPerformanceObservers().isEmpty())
+ return;
+
+ PerformanceObserverVector suspended;
+ copyToVector(suspendedPerformanceObservers(), suspended);
+ for (size_t i = 0; i < suspended.size(); ++i) {
+ if (!suspended[i]->shouldBeSuspended()) {
+ suspendedPerformanceObservers().remove(suspended[i]);
+ activateObserver(suspended[i]);
+ }
+ }
+}
+
+void PerformanceObserver::deliverObservations()
+{
+ ASSERT(isMainThread());
+ PerformanceObserverVector observers;
+ copyToVector(activePerformanceObservers(), observers);
+ activePerformanceObservers().clear();
+ std::sort(observers.begin(), observers.end(), ObserverLessThan());
+ for (size_t i = 0; i < observers.size(); ++i) {
+ if (observers[i]->shouldBeSuspended())
+ suspendedPerformanceObservers().add(observers[i]);
+ else
+ observers[i]->deliver();
+ }
+}
+
+DEFINE_TRACE(PerformanceObserver)
+{
+ visitor->trace(m_callback);
+ visitor->trace(m_performance);
+ visitor->trace(m_performanceEntries);
+ visitor->trace(m_registrations);
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698