Bug 782751 - User Timing API Implementation; r=baku

This commit is contained in:
Kyle Machulis 2015-01-30 09:29:36 -08:00
parent 9410a34c59
commit fc67bdcd0d
18 changed files with 475 additions and 27 deletions

View File

@ -19,8 +19,12 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceEntry)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
PerformanceEntry::PerformanceEntry(nsPerformance* aPerformance)
: mPerformance(aPerformance)
PerformanceEntry::PerformanceEntry(nsPerformance* aPerformance,
const nsAString& aName,
const nsAString& aEntryType)
: mPerformance(aPerformance),
mName(aName),
mEntryType(aEntryType)
{
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
}

View File

@ -20,7 +20,9 @@ protected:
virtual ~PerformanceEntry();
public:
explicit PerformanceEntry(nsPerformance* aPerformance);
PerformanceEntry(nsPerformance* aPerformance,
const nsAString& aName,
const nsAString& aEntryType);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PerformanceEntry)

View File

@ -0,0 +1,27 @@
/* -*- Mode: C++; 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/. */
#include "PerformanceMark.h"
#include "mozilla/dom/PerformanceMarkBinding.h"
using namespace mozilla::dom;
PerformanceMark::PerformanceMark(nsPerformance* aPerformance,
const nsAString& aName)
: PerformanceEntry(aPerformance, aName, NS_LITERAL_STRING("mark"))
{
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
mStartTime = aPerformance->GetDOMTiming()->TimeStampToDOMHighRes(mozilla::TimeStamp::Now());
}
PerformanceMark::~PerformanceMark()
{
}
JSObject*
PerformanceMark::WrapObject(JSContext* aCx)
{
return PerformanceMarkBinding::Wrap(aCx, this);
}

View File

@ -0,0 +1,36 @@
/* -*- Mode: C++; 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/. */
#ifndef mozilla_dom_performancemark_h___
#define mozilla_dom_performancemark_h___
#include "mozilla/dom/PerformanceEntry.h"
namespace mozilla {
namespace dom {
// http://www.w3.org/TR/user-timing/#performancemark
class PerformanceMark MOZ_FINAL : public PerformanceEntry
{
public:
PerformanceMark(nsPerformance* aPerformance,
const nsAString& aName);
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
virtual DOMHighResTimeStamp StartTime() const MOZ_OVERRIDE
{
return mStartTime;
}
protected:
virtual ~PerformanceMark();
DOMHighResTimeStamp mStartTime;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_performancemark_h___ */

View File

@ -0,0 +1,30 @@
/* -*- Mode: C++; 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/. */
#include "PerformanceMeasure.h"
#include "mozilla/dom/PerformanceMeasureBinding.h"
using namespace mozilla::dom;
PerformanceMeasure::PerformanceMeasure(nsPerformance* aPerformance,
const nsAString& aName,
DOMHighResTimeStamp aStartTime,
DOMHighResTimeStamp aEndTime)
: PerformanceEntry(aPerformance, aName, NS_LITERAL_STRING("measure")),
mStartTime(aStartTime),
mDuration(aEndTime - aStartTime)
{
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
}
PerformanceMeasure::~PerformanceMeasure()
{
}
JSObject*
PerformanceMeasure::WrapObject(JSContext* aCx)
{
return PerformanceMeasureBinding::Wrap(aCx, this);
}

View File

@ -0,0 +1,44 @@
/* -*- Mode: C++; 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/. */
#ifndef mozilla_dom_performancemeasure_h___
#define mozilla_dom_performancemeasure_h___
#include "mozilla/dom/PerformanceEntry.h"
namespace mozilla {
namespace dom {
// http://www.w3.org/TR/user-timing/#performancemeasure
class PerformanceMeasure MOZ_FINAL : public PerformanceEntry
{
public:
PerformanceMeasure(nsPerformance* aPerformance,
const nsAString& aName,
DOMHighResTimeStamp aStartTime,
DOMHighResTimeStamp aEndTime);
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
virtual DOMHighResTimeStamp StartTime() const MOZ_OVERRIDE
{
return mStartTime;
}
virtual DOMHighResTimeStamp Duration() const MOZ_OVERRIDE
{
return mDuration;
}
protected:
virtual ~PerformanceMeasure();
DOMHighResTimeStamp mStartTime;
DOMHighResTimeStamp mDuration;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_performancemeasure_h___ */

View File

@ -23,8 +23,9 @@ NS_IMPL_ADDREF_INHERITED(PerformanceResourceTiming, PerformanceEntry)
NS_IMPL_RELEASE_INHERITED(PerformanceResourceTiming, PerformanceEntry)
PerformanceResourceTiming::PerformanceResourceTiming(nsPerformanceTiming* aPerformanceTiming,
nsPerformance* aPerformance)
: PerformanceEntry(aPerformance),
nsPerformance* aPerformance,
const nsAString& aName)
: PerformanceEntry(aPerformance, aName, NS_LITERAL_STRING("resource")),
mTiming(aPerformanceTiming)
{
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");

View File

@ -28,7 +28,8 @@ public:
PerformanceEntry)
PerformanceResourceTiming(nsPerformanceTiming* aPerformanceTiming,
nsPerformance* aPerformance);
nsPerformance* aPerformance,
const nsAString& aName);
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;

View File

@ -181,6 +181,8 @@ EXPORTS.mozilla.dom += [
'NodeInfoInlines.h',
'NodeIterator.h',
'PerformanceEntry.h',
'PerformanceMark.h',
'PerformanceMeasure.h',
'PerformanceResourceTiming.h',
'ResponsiveImageSelector.h',
'ScreenOrientation.h',
@ -315,6 +317,8 @@ UNIFIED_SOURCES += [
'nsXMLHttpRequest.cpp',
'nsXMLNameSpaceMap.cpp',
'PerformanceEntry.cpp',
'PerformanceMark.cpp',
'PerformanceMeasure.cpp',
'PerformanceResourceTiming.cpp',
'ResponsiveImageSelector.cpp',
'ScriptSettings.cpp',

View File

@ -14,6 +14,7 @@
#include "mozilla/dom/Attr.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/NamedNodeMapBinding.h"
#include "mozilla/dom/NodeInfoInlines.h"
#include "nsAttrName.h"
#include "nsContentUtils.h"
#include "nsError.h"

View File

@ -11,17 +11,21 @@
#include "nsContentUtils.h"
#include "nsIScriptSecurityManager.h"
#include "nsIDOMWindow.h"
#include "nsILoadInfo.h"
#include "nsIURI.h"
#include "nsThreadUtils.h"
#include "PerformanceEntry.h"
#include "PerformanceMark.h"
#include "PerformanceMeasure.h"
#include "PerformanceResourceTiming.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/PerformanceBinding.h"
#include "mozilla/dom/PerformanceTimingBinding.h"
#include "mozilla/dom/PerformanceNavigationBinding.h"
#include "mozilla/TimeStamp.h"
#include "nsThreadUtils.h"
#include "nsILoadInfo.h"
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsPerformanceTiming, mPerformance)
@ -325,7 +329,7 @@ nsPerformanceTiming::ResponseStart()
DOMHighResTimeStamp
nsPerformanceTiming::ResponseEndHighRes()
{
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
if (!IsInitialized()) {
return mZeroTime;
}
if (mResponseEnd.IsNull() ||
@ -350,7 +354,7 @@ nsPerformanceTiming::IsInitialized() const
JSObject*
nsPerformanceTiming::WrapObject(JSContext *cx)
{
return dom::PerformanceTimingBinding::Wrap(cx, this);
return PerformanceTimingBinding::Wrap(cx, this);
}
@ -372,7 +376,7 @@ nsPerformanceNavigation::~nsPerformanceNavigation()
JSObject*
nsPerformanceNavigation::WrapObject(JSContext *cx)
{
return dom::PerformanceNavigationBinding::Wrap(cx, this);
return PerformanceNavigationBinding::Wrap(cx, this);
}
@ -449,13 +453,13 @@ nsPerformance::Navigation()
DOMHighResTimeStamp
nsPerformance::Now()
{
return GetDOMTiming()->TimeStampToDOMHighRes(mozilla::TimeStamp::Now());
return GetDOMTiming()->TimeStampToDOMHighRes(TimeStamp::Now());
}
JSObject*
nsPerformance::WrapObject(JSContext *cx)
{
return dom::PerformanceBinding::Wrap(cx, this);
return PerformanceBinding::Wrap(cx, this);
}
void
@ -483,7 +487,7 @@ nsPerformance::GetEntriesByType(const nsAString& entryType,
void
nsPerformance::GetEntriesByName(const nsAString& name,
const mozilla::dom::Optional<nsAString>& entryType,
const Optional<nsAString>& entryType,
nsTArray<nsRefPtr<PerformanceEntry> >& retval)
{
MOZ_ASSERT(NS_IsMainThread());
@ -499,11 +503,28 @@ nsPerformance::GetEntriesByName(const nsAString& name,
}
}
void
nsPerformance::ClearEntries(const Optional<nsAString>& aEntryName,
const nsAString& aEntryType)
{
for (uint32_t i = 0; i < mEntries.Length();) {
if ((!aEntryName.WasPassed() ||
mEntries[i]->GetName().Equals(aEntryName.Value())) &&
(aEntryType.IsEmpty() ||
mEntries[i]->GetEntryType().Equals(aEntryType))) {
mEntries.RemoveElementAt(i);
} else {
++i;
}
}
}
void
nsPerformance::ClearResourceTimings()
{
MOZ_ASSERT(NS_IsMainThread());
mEntries.Clear();
ClearEntries(Optional<nsAString>(),
NS_LITERAL_STRING("resource"));
}
void
@ -529,6 +550,7 @@ nsPerformance::AddEntry(nsIHttpChannel* channel,
// Don't add the entry if the buffer is full
if (mEntries.Length() >= mPrimaryBufferSize) {
NS_WARNING("Performance Entry buffer size maximum reached!");
return;
}
@ -558,24 +580,16 @@ nsPerformance::AddEntry(nsIHttpChannel* channel,
// The PerformanceResourceTiming object will use the nsPerformanceTiming
// object to get all the required timings.
nsRefPtr<dom::PerformanceResourceTiming> performanceEntry =
new dom::PerformanceResourceTiming(performanceTiming, this);
nsRefPtr<PerformanceResourceTiming> performanceEntry =
new PerformanceResourceTiming(performanceTiming, this, entryName);
performanceEntry->SetName(entryName);
performanceEntry->SetEntryType(NS_LITERAL_STRING("resource"));
// If the initiator type had no valid value, then set it to the default
// ("other") value.
if (initiatorType.IsEmpty()) {
initiatorType = NS_LITERAL_STRING("other");
}
performanceEntry->SetInitiatorType(initiatorType);
mEntries.InsertElementSorted(performanceEntry,
PerformanceEntryComparator());
if (mEntries.Length() >= mPrimaryBufferSize) {
// call onresourcetimingbufferfull
DispatchBufferFullEvent();
}
InsertPerformanceEntry(performanceEntry);
}
}
@ -598,3 +612,226 @@ nsPerformance::PerformanceEntryComparator::LessThan(
"Trying to compare null performance entries");
return aElem1->StartTime() < aElem2->StartTime();
}
void
nsPerformance::InsertPerformanceEntry(PerformanceEntry* aEntry)
{
MOZ_ASSERT(aEntry);
MOZ_ASSERT(mEntries.Length() < mPrimaryBufferSize);
if (mEntries.Length() == mPrimaryBufferSize) {
NS_WARNING("Performance Entry buffer size maximum reached!");
return;
}
mEntries.InsertElementSorted(aEntry,
PerformanceEntryComparator());
if (mEntries.Length() == mPrimaryBufferSize) {
// call onresourcetimingbufferfull
DispatchBufferFullEvent();
}
}
void
nsPerformance::Mark(const nsAString& aName, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
// Don't add the entry if the buffer is full
if (mEntries.Length() >= mPrimaryBufferSize) {
NS_WARNING("Performance Entry buffer size maximum reached!");
return;
}
if (IsPerformanceTimingAttribute(aName)) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
nsRefPtr<PerformanceMark> performanceMark =
new PerformanceMark(this, aName);
InsertPerformanceEntry(performanceMark);
}
void
nsPerformance::ClearMarks(const Optional<nsAString>& aName)
{
MOZ_ASSERT(NS_IsMainThread());
ClearEntries(aName, NS_LITERAL_STRING("mark"));
}
DOMHighResTimeStamp
nsPerformance::ResolveTimestampFromName(const nsAString& aName,
ErrorResult& aRv)
{
nsAutoTArray<nsRefPtr<PerformanceEntry>, 1> arr;
DOMHighResTimeStamp ts;
Optional<nsAString> typeParam;
nsAutoString str;
str.AssignLiteral("mark");
typeParam = &str;
GetEntriesByName(aName, typeParam, arr);
if (!arr.IsEmpty()) {
return arr.LastElement()->StartTime();
}
if (!IsPerformanceTimingAttribute(aName)) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return 0;
}
ts = GetPerformanceTimingFromString(aName);
if (!ts) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return 0;
}
return ConvertDOMMilliSecToHighRes(ts);
}
void
nsPerformance::Measure(const nsAString& aName,
const Optional<nsAString>& aStartMark,
const Optional<nsAString>& aEndMark,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
// Don't add the entry if the buffer is full
if (mEntries.Length() >= mPrimaryBufferSize) {
NS_WARNING("Performance Entry buffer size maximum reached!");
return;
}
DOMHighResTimeStamp startTime;
DOMHighResTimeStamp endTime;
if (IsPerformanceTimingAttribute(aName)) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
if (aStartMark.WasPassed()) {
startTime = ResolveTimestampFromName(aStartMark.Value(), aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
} else {
// Navigation start is used in this case, but since DOMHighResTimeStamp is
// in relation to navigation start, this will be zero if a name is not
// passed.
startTime = 0;
}
if (aEndMark.WasPassed()) {
endTime = ResolveTimestampFromName(aEndMark.Value(), aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
} else {
endTime = Now();
}
nsRefPtr<PerformanceMeasure> performanceMeasure =
new PerformanceMeasure(this, aName, startTime, endTime);
InsertPerformanceEntry(performanceMeasure);
}
void
nsPerformance::ClearMeasures(const Optional<nsAString>& aName)
{
MOZ_ASSERT(NS_IsMainThread());
ClearEntries(aName, NS_LITERAL_STRING("measure"));
}
DOMHighResTimeStamp
nsPerformance::ConvertDOMMilliSecToHighRes(DOMTimeMilliSec aTime) {
// If the time we're trying to convert is equal to zero, it hasn't been set
// yet so just return 0.
if (aTime == 0) {
return 0;
}
return aTime - GetDOMTiming()->GetNavigationStart();
}
// To be removed once bug 1124165 lands
bool
nsPerformance::IsPerformanceTimingAttribute(const nsAString& aName)
{
// Note that toJSON is added to this list due to bug 1047848
static const char* attributes[] =
{"navigationStart", "unloadEventStart", "unloadEventEnd", "redirectStart",
"redirectEnd", "fetchStart", "domainLookupStart", "domainLookupEnd",
"connectStart", "connectEnd", "requestStart", "responseStart",
"responseEnd", "domLoading", "domInteractive", "domContentLoadedEventStart",
"domContentLoadedEventEnd", "domComplete", "loadEventStart",
"loadEventEnd", nullptr};
for (uint32_t i = 0; attributes[i]; ++i) {
if (aName.EqualsASCII(attributes[i])) {
return true;
}
}
return false;
}
DOMTimeMilliSec
nsPerformance::GetPerformanceTimingFromString(const nsAString& aProperty)
{
if (!IsPerformanceTimingAttribute(aProperty)) {
return 0;
}
if (aProperty.EqualsLiteral("navigationStart")) {
// DOMHighResTimeStamp is in relation to navigationStart, so this will be
// zero.
return GetDOMTiming()->GetNavigationStart();
}
if (aProperty.EqualsLiteral("unloadEventStart")) {
return GetDOMTiming()->GetUnloadEventStart();
}
if (aProperty.EqualsLiteral("unloadEventEnd")) {
return GetDOMTiming()->GetUnloadEventEnd();
}
if (aProperty.EqualsLiteral("redirectStart")) {
return Timing()->RedirectStart();
}
if (aProperty.EqualsLiteral("redirectEnd")) {
return Timing()->RedirectEnd();
}
if (aProperty.EqualsLiteral("fetchStart")) {
return Timing()->FetchStart();
}
if (aProperty.EqualsLiteral("domainLookupStart")) {
return Timing()->DomainLookupStart();
}
if (aProperty.EqualsLiteral("domainLookupEnd")) {
return Timing()->DomainLookupEnd();
}
if (aProperty.EqualsLiteral("connectStart")) {
return Timing()->ConnectStart();
}
if (aProperty.EqualsLiteral("connectEnd")) {
return Timing()->ConnectEnd();
}
if (aProperty.EqualsLiteral("requestStart")) {
return Timing()->RequestStart();
}
if (aProperty.EqualsLiteral("responseStart")) {
return Timing()->ResponseStart();
}
if (aProperty.EqualsLiteral("responseEnd")) {
return Timing()->ResponseEnd();
}
if (aProperty.EqualsLiteral("domLoading")) {
return GetDOMTiming()->GetDomLoading();
}
if (aProperty.EqualsLiteral("domInteractive")) {
return GetDOMTiming()->GetDomInteractive();
}
if (aProperty.EqualsLiteral("domContentLoadedEventStart")) {
return GetDOMTiming()->GetDomContentLoadedEventStart();
}
if (aProperty.EqualsLiteral("domContentLoadedEventEnd")) {
return GetDOMTiming()->GetDomContentLoadedEventEnd();
}
if (aProperty.EqualsLiteral("domComplete")) {
return GetDOMTiming()->GetDomComplete();
}
if (aProperty.EqualsLiteral("loadEventStart")) {
return GetDOMTiming()->GetLoadEventStart();
}
if (aProperty.EqualsLiteral("loadEventEnd")) {
return GetDOMTiming()->GetLoadEventEnd();
}
MOZ_CRASH("IsPerformanceTimingAttribute and GetPerformanceTimingFromString are out of sync");
return 0;
}

View File

@ -21,6 +21,7 @@ class nsPerformance;
class nsIHttpChannel;
namespace mozilla {
class ErrorResult;
namespace dom {
class PerformanceEntry;
}
@ -335,12 +336,26 @@ public:
nsITimedChannel* timedChannel);
void ClearResourceTimings();
void SetResourceTimingBufferSize(uint64_t maxSize);
void Mark(const nsAString& aName, mozilla::ErrorResult& aRv);
void ClearMarks(const mozilla::dom::Optional<nsAString>& aName);
void Measure(const nsAString& aName,
const mozilla::dom::Optional<nsAString>& aStartMark,
const mozilla::dom::Optional<nsAString>& aEndMark,
mozilla::ErrorResult& aRv);
void ClearMeasures(const mozilla::dom::Optional<nsAString>& aName);
IMPL_EVENT_HANDLER(resourcetimingbufferfull)
private:
~nsPerformance();
bool IsPerformanceTimingAttribute(const nsAString& aName);
DOMHighResTimeStamp ResolveTimestampFromName(const nsAString& aName, mozilla::ErrorResult& aRv);
DOMTimeMilliSec GetPerformanceTimingFromString(const nsAString& aTimingName);
DOMHighResTimeStamp ConvertDOMMilliSecToHighRes(const DOMTimeMilliSec aTime);
void DispatchBufferFullEvent();
void InsertPerformanceEntry(PerformanceEntry* aEntry);
void ClearEntries(const mozilla::dom::Optional<nsAString>& aEntryName,
const nsAString& aEntryType);
nsCOMPtr<nsPIDOMWindow> mWindow;
nsRefPtr<nsDOMNavigationTiming> mDOMTiming;
nsCOMPtr<nsITimedChannel> mChannel;

View File

@ -859,6 +859,10 @@ var interfaceNamesInGlobalScope =
"Performance",
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceEntry",
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceMark",
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceMeasure",
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceNavigation",
// IMPORTANT: Do not change this list without review from a DOM peer!

View File

@ -51,3 +51,16 @@ partial interface Performance {
[Pref="dom.enable_resource_timing"]
attribute EventHandler onresourcetimingbufferfull;
};
// http://www.w3.org/TR/user-timing/
[Exposed=Window]
partial interface Performance {
[Pref="dom.enable_user_timing", Throws]
void mark(DOMString markName);
[Pref="dom.enable_user_timing"]
void clearMarks(optional DOMString markName);
[Pref="dom.enable_user_timing", Throws]
void measure(DOMString measureName, optional DOMString startMark, optional DOMString endMark);
[Pref="dom.enable_user_timing"]
void clearMeasures(optional DOMString measureName);
};

View File

@ -0,0 +1,12 @@
/* -*- 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
* http://www.w3.org/TR/user-timing/#performancemark
*/
interface PerformanceMark : PerformanceEntry
{
};

View File

@ -0,0 +1,12 @@
/* -*- 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
* http://www.w3.org/TR/user-timing/#performancemeasure
*/
interface PerformanceMeasure : PerformanceEntry
{
};

View File

@ -320,6 +320,8 @@ WEBIDL_FILES = [
'ParentNode.webidl',
'Performance.webidl',
'PerformanceEntry.webidl',
'PerformanceMark.webidl',
'PerformanceMeasure.webidl',
'PerformanceNavigation.webidl',
'PerformanceResourceTiming.webidl',
'PerformanceTiming.webidl',

View File

@ -144,6 +144,9 @@ pref("dom.enable_performance", true);
// Whether resource timing will be gathered and returned by performance.GetEntries*
pref("dom.enable_resource_timing", true);
// Enable high-resolution timing markers for users
pref("dom.enable_user_timing", true);
// Whether the Gamepad API is enabled
pref("dom.gamepad.enabled", true);
#ifdef RELEASE_BUILD