mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1165796 - Part 2: Implement PerformanceObserver.r=baku
This commit is contained in:
parent
84de9ab09d
commit
6281743182
@ -15,6 +15,7 @@ class nsISupports;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class PerformanceResourceTiming;
|
||||
|
||||
// http://www.w3.org/TR/performance-timeline/#performanceentry
|
||||
class PerformanceEntry : public nsISupports,
|
||||
@ -78,6 +79,11 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual const PerformanceResourceTiming* ToResourceTiming() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
nsString mName;
|
||||
|
154
dom/base/PerformanceObserver.cpp
Normal file
154
dom/base/PerformanceObserver.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "PerformanceObserver.h"
|
||||
|
||||
#include "mozilla/dom/PerformanceBinding.h"
|
||||
#include "mozilla/dom/PerformanceEntryBinding.h"
|
||||
#include "mozilla/dom/PerformanceObserverBinding.h"
|
||||
#include "mozilla/dom/workers/bindings/Performance.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsString.h"
|
||||
#include "PerformanceEntry.h"
|
||||
#include "PerformanceObserverEntryList.h"
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerScope.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::workers;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PerformanceObserver,
|
||||
mOwner,
|
||||
mPerformance,
|
||||
mCallback)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PerformanceObserver)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PerformanceObserver)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceObserver)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
PerformanceObserver::PerformanceObserver(nsPIDOMWindow* aOwner,
|
||||
PerformanceObserverCallback& aCb)
|
||||
: mOwner(aOwner)
|
||||
, mCallback(&aCb)
|
||||
{
|
||||
MOZ_ASSERT(mOwner);
|
||||
mPerformance = aOwner->GetPerformance();
|
||||
}
|
||||
|
||||
PerformanceObserver::PerformanceObserver(WorkerPrivate* aWorkerPrivate,
|
||||
PerformanceObserverCallback& aCb)
|
||||
: mCallback(&aCb)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
mPerformance = aWorkerPrivate->GlobalScope()->GetPerformance();
|
||||
}
|
||||
|
||||
PerformanceObserver::~PerformanceObserver()
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<PerformanceObserver>
|
||||
PerformanceObserver::Constructor(const GlobalObject& aGlobal,
|
||||
PerformanceObserverCallback& aCb,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsPIDOMWindow> ownerWindow =
|
||||
do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!ownerWindow) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(ownerWindow->IsInnerWindow());
|
||||
|
||||
nsRefPtr<PerformanceObserver> observer =
|
||||
new PerformanceObserver(ownerWindow, aCb);
|
||||
return observer.forget();
|
||||
}
|
||||
|
||||
JSContext* cx = aGlobal.Context();
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
nsRefPtr<PerformanceObserver> observer =
|
||||
new PerformanceObserver(workerPrivate, aCb);
|
||||
return observer.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
PerformanceObserver::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return PerformanceObserverBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceObserver::Notify(PerformanceEntry* aEntry)
|
||||
{
|
||||
MOZ_ASSERT(aEntry);
|
||||
|
||||
nsAutoString entryType;
|
||||
aEntry->GetEntryType(entryType);
|
||||
if (!mEntryTypes.Contains<nsString>(entryType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<PerformanceObserverEntryList> list = new PerformanceObserverEntryList(this);
|
||||
list->AppendEntry(aEntry);
|
||||
|
||||
ErrorResult rv;
|
||||
mCallback->Call(this, *list, *this, rv);
|
||||
NS_WARN_IF(rv.Failed());
|
||||
}
|
||||
|
||||
static nsString sValidTypeNames[7] = {
|
||||
NS_LITERAL_STRING("composite"),
|
||||
NS_LITERAL_STRING("mark"),
|
||||
NS_LITERAL_STRING("measure"),
|
||||
NS_LITERAL_STRING("navigation"),
|
||||
NS_LITERAL_STRING("render"),
|
||||
NS_LITERAL_STRING("resource"),
|
||||
NS_LITERAL_STRING("server")
|
||||
};
|
||||
|
||||
void
|
||||
PerformanceObserver::Observe(const PerformanceObserverInit& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aOptions.mEntryTypes.IsEmpty()) {
|
||||
aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<nsString> validEntryTypes;
|
||||
|
||||
for (const nsString& validTypeName : sValidTypeNames) {
|
||||
if (aOptions.mEntryTypes.Contains<nsString>(validTypeName) &&
|
||||
!validEntryTypes.Contains<nsString>(validTypeName)) {
|
||||
validEntryTypes.AppendElement(validTypeName);
|
||||
}
|
||||
}
|
||||
|
||||
if (validEntryTypes.IsEmpty()) {
|
||||
aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
mEntryTypes = validEntryTypes;
|
||||
|
||||
mPerformance->AddObserver(this);
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceObserver::Disconnect()
|
||||
{
|
||||
mPerformance->RemoveObserver(this);
|
||||
}
|
76
dom/base/PerformanceObserver.h
Normal file
76
dom/base/PerformanceObserver.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_PerformanceObserver_h__
|
||||
#define mozilla_dom_PerformanceObserver_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "mozilla/nsRefPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsPIDOMWindow;
|
||||
class PerformanceBase;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class GlobalObject;
|
||||
class PerformanceEntry;
|
||||
class PerformanceObserverCallback;
|
||||
struct PerformanceObserverInit;
|
||||
namespace workers {
|
||||
class WorkerPrivate;
|
||||
} // namespace workers
|
||||
|
||||
class PerformanceObserver final : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PerformanceObserver)
|
||||
|
||||
static already_AddRefed<PerformanceObserver>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
PerformanceObserverCallback& aCb,
|
||||
ErrorResult& aRv);
|
||||
|
||||
PerformanceObserver(nsPIDOMWindow* aOwner,
|
||||
PerformanceObserverCallback& aCb);
|
||||
|
||||
PerformanceObserver(workers::WorkerPrivate* aWorkerPrivate,
|
||||
PerformanceObserverCallback& aCb);
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
nsISupports* GetParentObject() const { return mOwner; }
|
||||
|
||||
void Observe(const PerformanceObserverInit& aOptions,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
void Disconnect();
|
||||
|
||||
void Notify(PerformanceEntry* entry);
|
||||
|
||||
private:
|
||||
~PerformanceObserver();
|
||||
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsRefPtr<PerformanceObserverCallback> mCallback;
|
||||
nsRefPtr<PerformanceBase> mPerformance;
|
||||
nsTArray<nsString> mEntryTypes;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
100
dom/base/PerformanceObserverEntryList.cpp
Normal file
100
dom/base/PerformanceObserverEntryList.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "PerformanceObserverEntryList.h"
|
||||
|
||||
#include "mozilla/dom/PerformanceObserverEntryListBinding.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsString.h"
|
||||
#include "PerformanceResourceTiming.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PerformanceObserverEntryList,
|
||||
mOwner,
|
||||
mEntries)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PerformanceObserverEntryList)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PerformanceObserverEntryList)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceObserverEntryList)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
PerformanceObserverEntryList::~PerformanceObserverEntryList()
|
||||
{
|
||||
}
|
||||
|
||||
JSObject*
|
||||
PerformanceObserverEntryList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return PerformanceObserverEntryListBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceObserverEntryList::GetEntries(
|
||||
const PerformanceEntryFilterOptions& aFilter,
|
||||
nsTArray<nsRefPtr<PerformanceEntry>>& aRetval)
|
||||
{
|
||||
aRetval.Clear();
|
||||
for (const nsRefPtr<PerformanceEntry>& entry : mEntries) {
|
||||
const PerformanceResourceTiming* resourceEntry =
|
||||
entry->ToResourceTiming();
|
||||
if (aFilter.mInitiatorType.WasPassed() && resourceEntry) {
|
||||
nsAutoString initiatorType;
|
||||
resourceEntry->GetInitiatorType(initiatorType);
|
||||
if (!initiatorType.Equals(aFilter.mInitiatorType.Value())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (aFilter.mName.WasPassed() &&
|
||||
!entry->GetName().Equals(aFilter.mName.Value())) {
|
||||
continue;
|
||||
}
|
||||
if (aFilter.mEntryType.WasPassed() &&
|
||||
!entry->GetEntryType().Equals(aFilter.mEntryType.Value())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
aRetval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceObserverEntryList::GetEntriesByType(
|
||||
const nsAString& aEntryType,
|
||||
nsTArray<nsRefPtr<PerformanceEntry>>& aRetval)
|
||||
{
|
||||
aRetval.Clear();
|
||||
for (const nsRefPtr<PerformanceEntry>& entry : mEntries) {
|
||||
if (entry->GetEntryType().Equals(aEntryType)) {
|
||||
aRetval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceObserverEntryList::GetEntriesByName(
|
||||
const nsAString& aName,
|
||||
const Optional<nsAString>& aEntryType,
|
||||
nsTArray<nsRefPtr<PerformanceEntry>>& aRetval)
|
||||
{
|
||||
aRetval.Clear();
|
||||
for (const nsRefPtr<PerformanceEntry>& entry : mEntries) {
|
||||
if (entry->GetName().Equals(aName)) {
|
||||
aRetval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceObserverEntryList::AppendEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
mEntries.AppendElement(aEntry);
|
||||
}
|
||||
|
64
dom/base/PerformanceObserverEntryList.h
Normal file
64
dom/base/PerformanceObserverEntryList.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_PerformanceObserverEntryList_h__
|
||||
#define mozilla_dom_PerformanceObserverEntryList_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/dom/PerformanceEntryBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct PerformanceEntryFilterOptions;
|
||||
class PerformanceEntry;
|
||||
template<typename T> class Optional;
|
||||
|
||||
class PerformanceObserverEntryList final : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
~PerformanceObserverEntryList();
|
||||
|
||||
public:
|
||||
explicit PerformanceObserverEntryList(nsISupports* aOwner)
|
||||
: mOwner(aOwner)
|
||||
{
|
||||
}
|
||||
|
||||
nsISupports* GetParentObject() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PerformanceObserverEntryList)
|
||||
|
||||
void GetEntries(const PerformanceEntryFilterOptions& aFilter,
|
||||
nsTArray<nsRefPtr<PerformanceEntry>>& aRetval);
|
||||
void GetEntriesByType(const nsAString& aEntryType,
|
||||
nsTArray<nsRefPtr<PerformanceEntry>>& aRetval);
|
||||
void GetEntriesByName(const nsAString& aName,
|
||||
const Optional<nsAString>& aEntryType,
|
||||
nsTArray<nsRefPtr<PerformanceEntry>>& aRetval);
|
||||
|
||||
void AppendEntry(PerformanceEntry* aEntry);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsTArray<nsRefPtr<PerformanceEntry>> mEntries;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif
|
@ -123,6 +123,11 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual const PerformanceResourceTiming* ToResourceTiming() const override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~PerformanceResourceTiming();
|
||||
|
||||
|
@ -189,6 +189,8 @@ EXPORTS.mozilla.dom += [
|
||||
'PerformanceEntry.h',
|
||||
'PerformanceMark.h',
|
||||
'PerformanceMeasure.h',
|
||||
'PerformanceObserver.h',
|
||||
'PerformanceObserverEntryList.h',
|
||||
'PerformanceResourceTiming.h',
|
||||
'ProcessGlobal.h',
|
||||
'ResponsiveImageSelector.h',
|
||||
@ -328,6 +330,8 @@ UNIFIED_SOURCES += [
|
||||
'PerformanceEntry.cpp',
|
||||
'PerformanceMark.cpp',
|
||||
'PerformanceMeasure.cpp',
|
||||
'PerformanceObserver.cpp',
|
||||
'PerformanceObserverEntryList.cpp',
|
||||
'PerformanceResourceTiming.cpp',
|
||||
'PostMessageEvent.cpp',
|
||||
'ProcessGlobal.cpp',
|
||||
|
@ -18,12 +18,14 @@
|
||||
#include "PerformanceEntry.h"
|
||||
#include "PerformanceMark.h"
|
||||
#include "PerformanceMeasure.h"
|
||||
#include "PerformanceObserver.h"
|
||||
#include "PerformanceResourceTiming.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/PerformanceBinding.h"
|
||||
#include "mozilla/dom/PerformanceEntryEvent.h"
|
||||
#include "mozilla/dom/PerformanceTimingBinding.h"
|
||||
#include "mozilla/dom/PerformanceNavigationBinding.h"
|
||||
#include "mozilla/dom/PerformanceObserverBinding.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
@ -737,6 +739,25 @@ nsPerformance::IsEnabled(JSContext* aCx, JSObject* aGlobal)
|
||||
return runnable->IsEnabled();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsPerformance::IsObserverEnabled(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
return Preferences::GetBool("dom.enable_performance_observer", false);
|
||||
}
|
||||
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<PrefEnabledRunnable> runnable =
|
||||
new PrefEnabledRunnable(workerPrivate,
|
||||
NS_LITERAL_CSTRING("dom.enable_performance_observer"));
|
||||
runnable->Dispatch(workerPrivate->GetJSContext());
|
||||
|
||||
return runnable->IsEnabled();
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::InsertUserEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
@ -1028,6 +1049,10 @@ PerformanceBase::InsertUserEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
mUserEntries.InsertElementSorted(aEntry,
|
||||
PerformanceEntryComparator());
|
||||
|
||||
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
|
||||
PerformanceObserver,
|
||||
Notify, (aEntry));
|
||||
}
|
||||
|
||||
void
|
||||
@ -1051,4 +1076,19 @@ PerformanceBase::InsertResourceEntry(PerformanceEntry* aEntry)
|
||||
// call onresourcetimingbufferfull
|
||||
DispatchBufferFullEvent();
|
||||
}
|
||||
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
|
||||
PerformanceObserver,
|
||||
Notify, (aEntry));
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::AddObserver(PerformanceObserver* aObserver)
|
||||
{
|
||||
mObservers.AppendElementUnlessExists(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::RemoveObserver(PerformanceObserver* aObserver)
|
||||
{
|
||||
mObservers.RemoveElement(aObserver);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace mozilla {
|
||||
class ErrorResult;
|
||||
namespace dom {
|
||||
class PerformanceEntry;
|
||||
class PerformanceObserver;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@ -300,6 +301,7 @@ public:
|
||||
explicit PerformanceBase(nsPIDOMWindow* aWindow);
|
||||
|
||||
typedef mozilla::dom::PerformanceEntry PerformanceEntry;
|
||||
typedef mozilla::dom::PerformanceObserver PerformanceObserver;
|
||||
|
||||
void GetEntries(nsTArray<nsRefPtr<PerformanceEntry>>& aRetval);
|
||||
void GetEntriesByType(const nsAString& aEntryType,
|
||||
@ -321,6 +323,9 @@ public:
|
||||
|
||||
void SetResourceTimingBufferSize(uint64_t aMaxSize);
|
||||
|
||||
void AddObserver(PerformanceObserver* aObserver);
|
||||
void RemoveObserver(PerformanceObserver* aObserver);
|
||||
|
||||
protected:
|
||||
virtual ~PerformanceBase();
|
||||
|
||||
@ -353,6 +358,8 @@ protected:
|
||||
void LogEntry(PerformanceEntry* aEntry, const nsACString& aOwner) const;
|
||||
void TimingNotification(PerformanceEntry* aEntry, const nsACString& aOwner, uint64_t epoch);
|
||||
|
||||
nsTObserverArray<PerformanceObserver*> mObservers;
|
||||
|
||||
private:
|
||||
nsTArray<nsRefPtr<PerformanceEntry>> mUserEntries;
|
||||
nsTArray<nsRefPtr<PerformanceEntry>> mResourceEntries;
|
||||
@ -376,6 +383,8 @@ public:
|
||||
|
||||
static bool IsEnabled(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
static bool IsObserverEnabled(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
nsDOMNavigationTiming* GetDOMTiming() const
|
||||
{
|
||||
return mDOMTiming;
|
||||
|
@ -247,6 +247,8 @@ support-files =
|
||||
referrer_testserver.sjs
|
||||
script_postmessages_fileList.js
|
||||
iframe_postMessages.html
|
||||
test_performance_observer.js
|
||||
performance_observer.html
|
||||
|
||||
[test_anonymousContent_api.html]
|
||||
[test_anonymousContent_append_after_reflow.html]
|
||||
@ -805,6 +807,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
|
||||
[test_window_define_nonconfigurable.html]
|
||||
[test_root_iframe.html]
|
||||
[test_performance_observer.html]
|
||||
[test_performance_user_timing.html]
|
||||
[test_bug1126851.html]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g'
|
||||
|
63
dom/base/test/performance_observer.html
Normal file
63
dom/base/test/performance_observer.html
Normal file
@ -0,0 +1,63 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for performance observer</title>
|
||||
<script>
|
||||
'use strict';
|
||||
[
|
||||
"async_test", "test", "setup",
|
||||
"assert_true", "assert_equals", "assert_array_equals",
|
||||
"assert_throws"
|
||||
].forEach(func => {
|
||||
window[func] = opener[func].bind(opener);
|
||||
});
|
||||
function done() {
|
||||
opener.add_completion_callback(() => {
|
||||
self.close();
|
||||
});
|
||||
opener.done();
|
||||
}
|
||||
|
||||
</script>
|
||||
<script src="test_performance_observer.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
function promiseXHR(aUrl) {
|
||||
return new Promise(resolve => {
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.onload = resolve;
|
||||
xmlhttp.open("get", aUrl, true);
|
||||
xmlhttp.send();
|
||||
});
|
||||
}
|
||||
|
||||
async_test(t => {
|
||||
performance.clearResourceTimings();
|
||||
|
||||
var observedEntries = [];
|
||||
var observer = new PerformanceObserver(list => {
|
||||
list.getEntries().forEach(entry => observedEntries.push(entry));
|
||||
});
|
||||
observer.observe({entryTypes: ['resource']});
|
||||
|
||||
assert_equals(observedEntries.length, 0);
|
||||
|
||||
promiseXHR("test-data.json").then(t.step_func_done(() => {
|
||||
assert_equals(observedEntries.length, 1);
|
||||
assert_array_equals(observedEntries,
|
||||
performance.getEntriesByType("resource"),
|
||||
"Observed 'resource' entries should equal to entries obtained by getEntriesByType.");
|
||||
}));
|
||||
}, "resource-timing test");
|
||||
|
||||
done();
|
||||
|
||||
</script>
|
||||
</body>
|
17
dom/base/test/test_performance_observer.html
Normal file
17
dom/base/test/test_performance_observer.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test for performance observer</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id=log></div>
|
||||
<script>
|
||||
'use strict';
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.enable_performance_observer", true]]},
|
||||
function() {
|
||||
window.open("performance_observer.html");
|
||||
});
|
||||
</script>
|
236
dom/base/test/test_performance_observer.js
Normal file
236
dom/base/test/test_performance_observer.js
Normal file
@ -0,0 +1,236 @@
|
||||
setup({ explicit_done: true });
|
||||
|
||||
test(t => {
|
||||
assert_throws({name: "TypeError"}, function() {
|
||||
new PerformanceObserver();
|
||||
}, "PerformanceObserver constructor should throw TypeError if no argument is specified.");
|
||||
|
||||
assert_throws({name: "TypeError"}, function() {
|
||||
new PerformanceObserver({});
|
||||
}, "PerformanceObserver constructor should throw TypeError if the argument is not a function.");
|
||||
}, "Test that PerformanceObserver constructor throws exception");
|
||||
|
||||
test(t => {
|
||||
var observer = new PerformanceObserver(() => {
|
||||
});
|
||||
|
||||
assert_throws({name: "TypeError"}, function() {
|
||||
observer.observe();
|
||||
}, "observe() should throw TypeError exception if no option specified.");
|
||||
|
||||
assert_throws({name: "TypeError"}, function() {
|
||||
observer.observe({ unsupportedAttribute: "unsupported" });
|
||||
}, "obsrve() should throw TypeError exception if the option has no 'entryTypes' attribute.");
|
||||
|
||||
assert_throws({name: "TypeError"}, function() {
|
||||
observer.observe({ entryTypes: [] });
|
||||
}, "obsrve() should throw TypeError exception if 'entryTypes' attribute is an empty sequence.");
|
||||
|
||||
assert_throws({name: "TypeError"}, function() {
|
||||
observer.observe({ entryTypes: null });
|
||||
}, "obsrve() should throw TypeError exception if 'entryTypes' attribute is null.");
|
||||
|
||||
assert_throws({name: "TypeError"}, function() {
|
||||
observer.observe({ entryTypes: ["invalid"]});
|
||||
}, "obsrve() should throw TypeError exception if 'entryTypes' attribute value is invalid.");
|
||||
}, "Test that PerformanceObserver.observe throws exception");
|
||||
|
||||
test(t => {
|
||||
performance.clearMarks();
|
||||
performance.clearMeasures();
|
||||
|
||||
var observedEntries = [];
|
||||
var observer = new PerformanceObserver(list => {
|
||||
list.getEntries().forEach(entry => observedEntries.push(entry));
|
||||
});
|
||||
observer.observe({entryTypes: ['mark', 'measure']});
|
||||
|
||||
assert_equals(observedEntries.length, 0,
|
||||
"User timing entries should never be observed.");
|
||||
assert_equals(performance.getEntriesByType("mark").length, 0,
|
||||
"There should be no 'mark' entries.");
|
||||
assert_equals(performance.getEntriesByType("measure").length, 0,
|
||||
"There should be no 'measure' entries.");
|
||||
|
||||
performance.mark("test-start");
|
||||
performance.mark("test-end");
|
||||
performance.measure("test-measure", "test-start", "test-end");
|
||||
|
||||
assert_equals(observedEntries.length, 3,
|
||||
"There should be three observed entries.");
|
||||
|
||||
var markEntries = observedEntries.filter(entry => {
|
||||
return entry.entryType == "mark";
|
||||
});
|
||||
assert_array_equals(markEntries, performance.getEntriesByType("mark"),
|
||||
"Observed 'mark' entries should equal to entries obtained by getEntriesByType.");
|
||||
|
||||
var measureEntries = observedEntries.filter(entry => {
|
||||
return entry.entryType == "measure";
|
||||
});
|
||||
assert_array_equals(measureEntries, performance.getEntriesByType("measure"),
|
||||
"Observed 'measure' entries should equal to entries obtained by getEntriesByType.");
|
||||
}, "Test for user-timing with PerformanceObserver");
|
||||
|
||||
test(t => {
|
||||
performance.clearMarks();
|
||||
performance.clearMeasures();
|
||||
|
||||
var observedEntries = [];
|
||||
var observer = new PerformanceObserver(list => {
|
||||
list.getEntries().forEach(entry => observedEntries.push(entry));
|
||||
});
|
||||
observer.observe({entryTypes: ['mark', 'measure']});
|
||||
|
||||
observer.disconnect();
|
||||
|
||||
assert_equals(observedEntries.length, 0,
|
||||
"User timing entries should be never observed.");
|
||||
|
||||
performance.mark("test-start");
|
||||
performance.mark("test-end");
|
||||
performance.measure("test-measure", "test-start", "test-end");
|
||||
|
||||
assert_equals(performance.getEntriesByType("mark").length, 2);
|
||||
assert_equals(performance.getEntriesByType("measure").length, 1);
|
||||
|
||||
assert_equals(observedEntries.length, 0,
|
||||
"User timing entries should be never observed after disconnecting observer.");
|
||||
}, "Nothing should be notified after disconnecting observer");
|
||||
|
||||
test(t => {
|
||||
performance.clearMarks();
|
||||
performance.clearMeasures();
|
||||
|
||||
var observedEntryList;
|
||||
var observer = new PerformanceObserver(list => {
|
||||
observedEntryList = list;
|
||||
});
|
||||
observer.observe({entryTypes: ['mark']});
|
||||
|
||||
performance.mark("test");
|
||||
assert_array_equals(observedEntryList.getEntries({"entryType": "mark"}),
|
||||
performance.getEntriesByType("mark"),
|
||||
"getEntries with entryType filter should return correct results.");
|
||||
|
||||
assert_array_equals(observedEntryList.getEntries({"name": "test"}),
|
||||
performance.getEntriesByName("test"),
|
||||
"getEntries with name filter should return correct results.");
|
||||
|
||||
assert_array_equals(observedEntryList.getEntries({"name": "test",
|
||||
"entryType": "mark"}),
|
||||
performance.getEntriesByName("test"),
|
||||
"getEntries with name and entryType filter should return correct results.");
|
||||
|
||||
assert_array_equals(observedEntryList.getEntries({"name": "invalid"}),
|
||||
[],
|
||||
"getEntries with non-existent name filter should return an empty array.");
|
||||
|
||||
assert_array_equals(observedEntryList.getEntries({"name": "test",
|
||||
"entryType": "measure"}),
|
||||
[],
|
||||
"getEntries with name filter and non-existent entryType should return an empty array.");
|
||||
|
||||
assert_array_equals(observedEntryList.getEntries({"name": "invalid",
|
||||
"entryType": "mark"}),
|
||||
[],
|
||||
"getEntries with non-existent name and entryType filter should return an empty array.");
|
||||
}, "Test for PerformanceObserverEntryList.getEntries");
|
||||
|
||||
test(t => {
|
||||
performance.clearMarks();
|
||||
performance.clearMeasures();
|
||||
|
||||
var observedEntryList;
|
||||
var observer = new PerformanceObserver(list => {
|
||||
observedEntryList = list;
|
||||
});
|
||||
observer.observe({entryTypes: ['mark', 'measure']});
|
||||
|
||||
performance.mark("test");
|
||||
assert_array_equals(observedEntryList.getEntriesByType("mark"),
|
||||
performance.getEntriesByType("mark"));
|
||||
|
||||
performance.measure("test-measure", "test", "test");
|
||||
assert_array_equals(observedEntryList.getEntriesByType("measure"),
|
||||
performance.getEntriesByType("measure"));
|
||||
}, "Test for PerformanceObserverEntryList.getEntriesByType");
|
||||
|
||||
test(t => {
|
||||
performance.clearMarks();
|
||||
performance.clearMeasures();
|
||||
|
||||
var observedEntryList;
|
||||
var observer = new PerformanceObserver(list => {
|
||||
observedEntryList = list;
|
||||
});
|
||||
observer.observe({entryTypes: ['mark', 'measure']});
|
||||
|
||||
performance.mark("test");
|
||||
assert_array_equals(observedEntryList.getEntriesByName("test"),
|
||||
performance.getEntriesByName("test"));
|
||||
|
||||
performance.measure("test-measure", "test", "test");
|
||||
assert_array_equals(observedEntryList.getEntriesByName("test-measure"),
|
||||
performance.getEntriesByName("test-measure"));
|
||||
}, "Test for PerformanceObserverEntryList.getEntriesByName");
|
||||
|
||||
test(t => {
|
||||
performance.clearMarks();
|
||||
performance.clearMeasures();
|
||||
|
||||
var observedEntries = [];
|
||||
var observer = new PerformanceObserver(list => {
|
||||
list.getEntries().forEach(entry => observedEntries.push(entry));
|
||||
});
|
||||
|
||||
observer.observe({entryTypes: ['mark', 'measure']});
|
||||
observer.observe({entryTypes: ['mark', 'measure']});
|
||||
|
||||
performance.mark("test-start");
|
||||
performance.mark("test-end");
|
||||
performance.measure("test-measure", "test-start", "test-end");
|
||||
|
||||
assert_equals(observedEntries.length, 3,
|
||||
"Observed user timing entries should have only three entries.");
|
||||
}, "Test that invoking observe method twice affects nothing");
|
||||
|
||||
test(t => {
|
||||
performance.clearMarks();
|
||||
performance.clearMeasures();
|
||||
|
||||
var observedEntries = [];
|
||||
var observer = new PerformanceObserver(list => {
|
||||
list.getEntries().forEach(entry => observedEntries.push(entry));
|
||||
});
|
||||
|
||||
observer.observe({entryTypes: ['mark', 'measure']});
|
||||
observer.observe({entryTypes: ['mark']});
|
||||
|
||||
performance.mark("test-start");
|
||||
performance.mark("test-end");
|
||||
performance.measure("test-measure", "test-start", "test-end");
|
||||
|
||||
assert_equals(observedEntries.length, 2,
|
||||
"Observed user timing entries should have only two entries.");
|
||||
}, "Test that observing filter is replaced by a new filter");
|
||||
|
||||
test(t => {
|
||||
performance.clearMarks();
|
||||
performance.clearMeasures();
|
||||
|
||||
var observedEntries = [];
|
||||
var observer = new PerformanceObserver(list => {
|
||||
list.getEntries().forEach(entry => observedEntries.push(entry));
|
||||
});
|
||||
|
||||
observer.observe({entryTypes: ['mark']});
|
||||
observer.observe({entryTypes: ['measure']});
|
||||
|
||||
performance.mark("test-start");
|
||||
performance.mark("test-end");
|
||||
performance.measure("test-measure", "test-start", "test-end");
|
||||
|
||||
assert_equals(observedEntries.length, 1,
|
||||
"Observed user timing entries should have only 1 entries.");
|
||||
}, "Test that observing filter is replaced by a new filter");
|
@ -71,3 +71,4 @@ partial interface Performance {
|
||||
[Func="nsPerformance::IsEnabled"]
|
||||
void clearMeasures(optional DOMString measureName);
|
||||
};
|
||||
|
||||
|
23
dom/webidl/PerformanceObserver.webidl
Normal file
23
dom/webidl/PerformanceObserver.webidl
Normal file
@ -0,0 +1,23 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://w3c.github.io/performance-timeline/#the-performance-observer-interface
|
||||
*/
|
||||
|
||||
dictionary PerformanceObserverInit {
|
||||
required sequence<DOMString> entryTypes;
|
||||
};
|
||||
|
||||
callback PerformanceObserverCallback = void (PerformanceObserverEntryList entries, PerformanceObserver observer);
|
||||
|
||||
[Func="nsPerformance::IsObserverEnabled",
|
||||
Constructor(PerformanceObserverCallback callback),
|
||||
Exposed=(Window,Worker)]
|
||||
interface PerformanceObserver {
|
||||
[Throws]
|
||||
void observe(PerformanceObserverInit options);
|
||||
void disconnect();
|
||||
};
|
24
dom/webidl/PerformanceObserverEntryList.webidl
Normal file
24
dom/webidl/PerformanceObserverEntryList.webidl
Normal file
@ -0,0 +1,24 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://w3c.github.io/performance-timeline/#the-performanceobserverentrylist-interface
|
||||
*/
|
||||
|
||||
// XXX should be moved into Performance.webidl.
|
||||
dictionary PerformanceEntryFilterOptions {
|
||||
DOMString name;
|
||||
DOMString entryType;
|
||||
DOMString initiatorType;
|
||||
};
|
||||
|
||||
[Func="nsPerformance::IsObserverEnabled", Exposed=(Window,Worker)]
|
||||
interface PerformanceObserverEntryList {
|
||||
PerformanceEntryList getEntries(optional PerformanceEntryFilterOptions filter);
|
||||
PerformanceEntryList getEntriesByType(DOMString entryType);
|
||||
PerformanceEntryList getEntriesByName(DOMString name,
|
||||
optional DOMString entryType);
|
||||
};
|
||||
|
@ -353,6 +353,8 @@ WEBIDL_FILES = [
|
||||
'PerformanceMark.webidl',
|
||||
'PerformanceMeasure.webidl',
|
||||
'PerformanceNavigation.webidl',
|
||||
'PerformanceObserver.webidl',
|
||||
'PerformanceObserverEntryList.webidl',
|
||||
'PerformanceResourceTiming.webidl',
|
||||
'PerformanceTiming.webidl',
|
||||
'PeriodicWave.webidl',
|
||||
|
@ -106,8 +106,10 @@ support-files =
|
||||
bug1132924_worker.js
|
||||
empty.html
|
||||
worker_performance_user_timing.js
|
||||
worker_performance_observer.js
|
||||
sharedworker_performance_user_timing.js
|
||||
referrer.sjs
|
||||
performance_observer.html
|
||||
|
||||
[test_404.html]
|
||||
[test_atob.html]
|
||||
@ -168,6 +170,7 @@ skip-if = buildapp == 'mulet'
|
||||
[test_onLine.html]
|
||||
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_performance_user_timing.html]
|
||||
[test_performance_observer.html]
|
||||
[test_promise.html]
|
||||
[test_promise_resolved_with_string.html]
|
||||
[test_recursion.html]
|
||||
|
32
dom/workers/test/performance_observer.html
Normal file
32
dom/workers/test/performance_observer.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for performance observer in worker</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
[
|
||||
"async_test", "test", "setup",
|
||||
"assert_true", "assert_equals", "assert_array_equals",
|
||||
"assert_throws", "fetch_tests_from_worker"
|
||||
].forEach(func => {
|
||||
window[func] = opener[func].bind(opener);
|
||||
});
|
||||
|
||||
function done() {
|
||||
opener.add_completion_callback(() => {
|
||||
self.close();
|
||||
});
|
||||
opener.done();
|
||||
}
|
||||
|
||||
fetch_tests_from_worker(new Worker("worker_performance_observer.js"));
|
||||
done();
|
||||
</script>
|
||||
</body>
|
17
dom/workers/test/test_performance_observer.html
Normal file
17
dom/workers/test/test_performance_observer.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test for performance observer in worker</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id=log></div>
|
||||
<script>
|
||||
'use strict';
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.enable_performance_observer", true]]},
|
||||
function() {
|
||||
window.open("performance_observer.html");
|
||||
});
|
||||
</script>
|
4
dom/workers/test/worker_performance_observer.js
Normal file
4
dom/workers/test/worker_performance_observer.js
Normal file
@ -0,0 +1,4 @@
|
||||
importScripts(['/resources/testharness.js']);
|
||||
importScripts(['../../../dom/base/test/test_performance_observer.js']);
|
||||
|
||||
done();
|
Loading…
Reference in New Issue
Block a user