mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1278838
- Remove separate worker binding for Performance API, r=smaug
--HG-- rename : dom/performance/nsPerformance.cpp => dom/performance/Performance.cpp rename : dom/performance/nsPerformance.h => dom/performance/Performance.h rename : dom/workers/Performance.cpp => dom/performance/PerformanceWorker.cpp rename : dom/workers/Performance.h => dom/performance/PerformanceWorker.h
This commit is contained in:
parent
a8e509a525
commit
64734bf74c
@ -15,10 +15,10 @@
|
||||
#include "nsContentSecurityManager.h"
|
||||
#include "nsScreen.h"
|
||||
#include "nsHistory.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#include "nsIDOMStorageManager.h"
|
||||
#include "mozilla/dom/DOMStorage.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/StorageEvent.h"
|
||||
#include "mozilla/dom/StorageEventBinding.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
@ -2811,7 +2811,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
currentInner->AsInner()->CreatePerformanceObjectIfNeeded();
|
||||
if (currentInner->mPerformance) {
|
||||
newInnerWindow->mPerformance =
|
||||
new nsPerformance(newInnerWindow->AsInner(),
|
||||
Performance::CreateForMainThread(newInnerWindow->AsInner(),
|
||||
currentInner->mPerformance->GetDOMTiming(),
|
||||
currentInner->mPerformance->GetChannel(),
|
||||
currentInner->mPerformance->GetParentPerformance());
|
||||
@ -3832,7 +3832,7 @@ nsGlobalWindow::GetHistory(ErrorResult& aError)
|
||||
return mHistory;
|
||||
}
|
||||
|
||||
nsPerformance*
|
||||
Performance*
|
||||
nsPIDOMWindowInner::GetPerformance()
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow());
|
||||
@ -3840,7 +3840,7 @@ nsPIDOMWindowInner::GetPerformance()
|
||||
return mPerformance;
|
||||
}
|
||||
|
||||
nsPerformance*
|
||||
Performance*
|
||||
nsGlobalWindow::GetPerformance()
|
||||
{
|
||||
return AsInner()->GetPerformance();
|
||||
@ -3865,7 +3865,7 @@ nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded()
|
||||
if (timing) {
|
||||
// If we are dealing with an iframe, we will need the parent's performance
|
||||
// object (so we can add the iframe as a resource of that page).
|
||||
nsPerformance* parentPerformance = nullptr;
|
||||
Performance* parentPerformance = nullptr;
|
||||
nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
|
||||
if (parentWindow) {
|
||||
nsPIDOMWindowInner* parentInnerWindow = nullptr;
|
||||
@ -3877,7 +3877,8 @@ nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded()
|
||||
}
|
||||
}
|
||||
mPerformance =
|
||||
new nsPerformance(this, timing, timedChannel, parentPerformance);
|
||||
Performance::CreateForMainThread(this, timing, timedChannel,
|
||||
parentPerformance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1257,7 +1257,8 @@ public:
|
||||
|
||||
already_AddRefed<nsWindowRoot> GetWindowRootOuter();
|
||||
already_AddRefed<nsWindowRoot> GetWindowRoot(mozilla::ErrorResult& aError);
|
||||
nsPerformance* GetPerformance();
|
||||
|
||||
mozilla::dom::Performance* GetPerformance();
|
||||
|
||||
protected:
|
||||
// Web IDL helpers
|
||||
|
@ -31,7 +31,6 @@ class nsIDocument;
|
||||
class nsIIdleObserver;
|
||||
class nsIScriptTimeoutHandler;
|
||||
class nsIURI;
|
||||
class nsPerformance;
|
||||
class nsPIDOMWindowInner;
|
||||
class nsPIDOMWindowOuter;
|
||||
class nsPIWindowRoot;
|
||||
@ -44,6 +43,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
class AudioContext;
|
||||
class Element;
|
||||
class Performance;
|
||||
class ServiceWorkerRegistrationMainThread;
|
||||
} // namespace dom
|
||||
namespace gfx {
|
||||
@ -611,7 +611,7 @@ protected:
|
||||
nsIDocShell* MOZ_NON_OWNING_REF mDocShell; // Weak Reference
|
||||
|
||||
// mPerformance is only used on inner windows.
|
||||
RefPtr<nsPerformance> mPerformance;
|
||||
RefPtr<mozilla::dom::Performance> mPerformance;
|
||||
|
||||
typedef nsRefPtrHashtable<nsStringHashKey,
|
||||
mozilla::dom::ServiceWorkerRegistrationMainThread>
|
||||
@ -741,7 +741,7 @@ public:
|
||||
GetServiceWorkerRegistration(const nsAString& aScope);
|
||||
void InvalidateServiceWorkerRegistration(const nsAString& aScope);
|
||||
|
||||
nsPerformance* GetPerformance();
|
||||
mozilla::dom::Performance* GetPerformance();
|
||||
|
||||
bool HasMutationListeners(uint32_t aMutationEventType) const
|
||||
{
|
||||
|
@ -885,15 +885,6 @@ DOMInterfaces = {
|
||||
'wrapperCache': False
|
||||
},
|
||||
|
||||
'Performance': [{
|
||||
'nativeType': 'nsPerformance',
|
||||
},
|
||||
{
|
||||
'nativeType': 'mozilla::dom::workers::Performance',
|
||||
'headerFile': 'mozilla/dom/workers/bindings/Performance.h',
|
||||
'workers': True,
|
||||
}],
|
||||
|
||||
'Plugin': {
|
||||
'headerFile' : 'nsPluginArray.h',
|
||||
'nativeType': 'nsPluginElement',
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/Exceptions.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FunctionBinding.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/StructuredCloneHolder.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
@ -20,7 +21,6 @@
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "ScriptSettings.h"
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
@ -1355,7 +1355,7 @@ Console::MethodInternal(JSContext* aCx, MethodName aMethodName,
|
||||
nsGlobalWindow *win = nsGlobalWindow::Cast(mWindow);
|
||||
MOZ_ASSERT(win);
|
||||
|
||||
RefPtr<nsPerformance> performance = win->GetPerformance();
|
||||
RefPtr<Performance> performance = win->GetPerformance();
|
||||
if (!performance) {
|
||||
return;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "mozilla/InternalMutationEvent.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/MiscEvents.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
@ -30,7 +31,6 @@
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsPIWindowRoot.h"
|
||||
#include "WorkerPrivate.h"
|
||||
|
||||
@ -1096,7 +1096,8 @@ Event::TimeStamp() const
|
||||
if (NS_WARN_IF(!win)) {
|
||||
return 0.0;
|
||||
}
|
||||
nsPerformance* perf = win->GetPerformance();
|
||||
|
||||
Performance* perf = win->GetPerformance();
|
||||
if (NS_WARN_IF(!perf)) {
|
||||
return 0.0;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ Gamepad::UpdateTimestamp()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindowInner> newWindow(do_QueryInterface(mParent));
|
||||
if(newWindow) {
|
||||
nsPerformance* perf = newWindow->GetPerformance();
|
||||
Performance* perf = newWindow->GetPerformance();
|
||||
if (perf) {
|
||||
mTimestamp = perf->Now();
|
||||
}
|
||||
|
@ -10,12 +10,12 @@
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/GamepadBinding.h"
|
||||
#include "mozilla/dom/GamepadButton.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include <stdint.h>
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsPerformance.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/WakeLock.h"
|
||||
#include "mozilla/dom/power/PowerManagerService.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/VideoPlaybackQuality.h"
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT(Video)
|
||||
@ -235,7 +235,7 @@ HTMLVideoElement::GetVideoPlaybackQuality()
|
||||
|
||||
if (sVideoStatsEnabled) {
|
||||
if (nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow()) {
|
||||
nsPerformance* perf = window->GetPerformance();
|
||||
Performance* perf = window->GetPerformance();
|
||||
if (perf) {
|
||||
creationTime = perf->Now();
|
||||
}
|
||||
|
537
dom/performance/Performance.cpp
Normal file
537
dom/performance/Performance.cpp
Normal file
@ -0,0 +1,537 @@
|
||||
/* -*- 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 "Performance.h"
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
#include "PerformanceEntry.h"
|
||||
#include "PerformanceMainThread.h"
|
||||
#include "PerformanceMark.h"
|
||||
#include "PerformanceMeasure.h"
|
||||
#include "PerformanceObserver.h"
|
||||
#include "PerformanceResourceTiming.h"
|
||||
#include "PerformanceWorker.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/PerformanceBinding.h"
|
||||
#include "mozilla/dom/PerformanceEntryEvent.h"
|
||||
#include "mozilla/dom/PerformanceNavigationBinding.h"
|
||||
#include "mozilla/dom/PerformanceObserverBinding.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#define PERFLOG(msg, ...) __android_log_print(ANDROID_LOG_INFO, "PerformanceTiming", msg, ##__VA_ARGS__)
|
||||
#else
|
||||
#define PERFLOG(msg, ...) printf_stderr(msg, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using namespace workers;
|
||||
|
||||
namespace {
|
||||
|
||||
// Helper classes
|
||||
class MOZ_STACK_CLASS PerformanceEntryComparator final
|
||||
{
|
||||
public:
|
||||
bool Equals(const PerformanceEntry* aElem1,
|
||||
const PerformanceEntry* aElem2) const
|
||||
{
|
||||
MOZ_ASSERT(aElem1 && aElem2,
|
||||
"Trying to compare null performance entries");
|
||||
return aElem1->StartTime() == aElem2->StartTime();
|
||||
}
|
||||
|
||||
bool LessThan(const PerformanceEntry* aElem1,
|
||||
const PerformanceEntry* aElem2) const
|
||||
{
|
||||
MOZ_ASSERT(aElem1 && aElem2,
|
||||
"Trying to compare null performance entries");
|
||||
return aElem1->StartTime() < aElem2->StartTime();
|
||||
}
|
||||
};
|
||||
|
||||
class PrefEnabledRunnable final
|
||||
: public WorkerCheckAPIExposureOnMainThreadRunnable
|
||||
{
|
||||
public:
|
||||
PrefEnabledRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsCString& aPrefName)
|
||||
: WorkerCheckAPIExposureOnMainThreadRunnable(aWorkerPrivate)
|
||||
, mEnabled(false)
|
||||
, mPrefName(aPrefName)
|
||||
{ }
|
||||
|
||||
bool MainThreadRun() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mEnabled = Preferences::GetBool(mPrefName.get(), false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsEnabled() const
|
||||
{
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mEnabled;
|
||||
nsCString mPrefName;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Performance)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(Performance,
|
||||
DOMEventTargetHelper,
|
||||
mUserEntries,
|
||||
mResourceEntries);
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(Performance, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(Performance, DOMEventTargetHelper)
|
||||
|
||||
/* static */ already_AddRefed<Performance>
|
||||
Performance::CreateForMainThread(nsPIDOMWindowInner* aWindow,
|
||||
nsDOMNavigationTiming* aDOMTiming,
|
||||
nsITimedChannel* aChannel,
|
||||
Performance* aParentPerformance)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<Performance> performance =
|
||||
new PerformanceMainThread(aWindow, aDOMTiming, aChannel,
|
||||
aParentPerformance);
|
||||
return performance.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Performance>
|
||||
Performance::CreateForWorker(workers::WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<Performance> performance = new PerformanceWorker(aWorkerPrivate);
|
||||
return performance.forget();
|
||||
}
|
||||
|
||||
Performance::Performance()
|
||||
: mResourceTimingBufferSize(kDefaultResourceTimingBufferSize)
|
||||
, mPendingNotificationObserversTask(false)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
}
|
||||
|
||||
Performance::Performance(nsPIDOMWindowInner* aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mResourceTimingBufferSize(kDefaultResourceTimingBufferSize)
|
||||
, mPendingNotificationObserversTask(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
Performance::~Performance()
|
||||
{}
|
||||
|
||||
JSObject*
|
||||
Performance::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return PerformanceBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
Performance::GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval)
|
||||
{
|
||||
aRetval = mResourceEntries;
|
||||
aRetval.AppendElements(mUserEntries);
|
||||
aRetval.Sort(PerformanceEntryComparator());
|
||||
}
|
||||
|
||||
void
|
||||
Performance::GetEntriesByType(const nsAString& aEntryType,
|
||||
nsTArray<RefPtr<PerformanceEntry>>& aRetval)
|
||||
{
|
||||
if (aEntryType.EqualsLiteral("resource")) {
|
||||
aRetval = mResourceEntries;
|
||||
return;
|
||||
}
|
||||
|
||||
aRetval.Clear();
|
||||
|
||||
if (aEntryType.EqualsLiteral("mark") ||
|
||||
aEntryType.EqualsLiteral("measure")) {
|
||||
for (PerformanceEntry* entry : mUserEntries) {
|
||||
if (entry->GetEntryType().Equals(aEntryType)) {
|
||||
aRetval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Performance::GetEntriesByName(const nsAString& aName,
|
||||
const Optional<nsAString>& aEntryType,
|
||||
nsTArray<RefPtr<PerformanceEntry>>& aRetval)
|
||||
{
|
||||
aRetval.Clear();
|
||||
|
||||
for (PerformanceEntry* entry : mResourceEntries) {
|
||||
if (entry->GetName().Equals(aName) &&
|
||||
(!aEntryType.WasPassed() ||
|
||||
entry->GetEntryType().Equals(aEntryType.Value()))) {
|
||||
aRetval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
|
||||
for (PerformanceEntry* entry : mUserEntries) {
|
||||
if (entry->GetName().Equals(aName) &&
|
||||
(!aEntryType.WasPassed() ||
|
||||
entry->GetEntryType().Equals(aEntryType.Value()))) {
|
||||
aRetval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
|
||||
aRetval.Sort(PerformanceEntryComparator());
|
||||
}
|
||||
|
||||
void
|
||||
Performance::ClearUserEntries(const Optional<nsAString>& aEntryName,
|
||||
const nsAString& aEntryType)
|
||||
{
|
||||
for (uint32_t i = 0; i < mUserEntries.Length();) {
|
||||
if ((!aEntryName.WasPassed() ||
|
||||
mUserEntries[i]->GetName().Equals(aEntryName.Value())) &&
|
||||
(aEntryType.IsEmpty() ||
|
||||
mUserEntries[i]->GetEntryType().Equals(aEntryType))) {
|
||||
mUserEntries.RemoveElementAt(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Performance::ClearResourceTimings()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mResourceEntries.Clear();
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
Performance::RoundTime(double aTime) const
|
||||
{
|
||||
// Round down to the nearest 5us, because if the timer is too accurate people
|
||||
// can do nasty timing attacks with it. See similar code in the worker
|
||||
// Performance implementation.
|
||||
const double maxResolutionMs = 0.005;
|
||||
return floor(aTime / maxResolutionMs) * maxResolutionMs;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Performance::Mark(const nsAString& aName, ErrorResult& aRv)
|
||||
{
|
||||
// Don't add the entry if the buffer is full. XXX should be removed by bug 1159003.
|
||||
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsPerformanceTimingAttribute(aName)) {
|
||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<PerformanceMark> performanceMark =
|
||||
new PerformanceMark(GetAsISupports(), aName, Now());
|
||||
InsertUserEntry(performanceMark);
|
||||
|
||||
if (profiler_is_active()) {
|
||||
PROFILER_MARKER(NS_ConvertUTF16toUTF8(aName).get());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Performance::ClearMarks(const Optional<nsAString>& aName)
|
||||
{
|
||||
ClearUserEntries(aName, NS_LITERAL_STRING("mark"));
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
Performance::ResolveTimestampFromName(const nsAString& aName,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AutoTArray<RefPtr<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 ts - CreationTime();
|
||||
}
|
||||
|
||||
void
|
||||
Performance::Measure(const nsAString& aName,
|
||||
const Optional<nsAString>& aStartMark,
|
||||
const Optional<nsAString>& aEndMark,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// Don't add the entry if the buffer is full. XXX should be removed by bug
|
||||
// 1159003.
|
||||
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
|
||||
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();
|
||||
}
|
||||
|
||||
RefPtr<PerformanceMeasure> performanceMeasure =
|
||||
new PerformanceMeasure(GetAsISupports(), aName, startTime, endTime);
|
||||
InsertUserEntry(performanceMeasure);
|
||||
}
|
||||
|
||||
void
|
||||
Performance::ClearMeasures(const Optional<nsAString>& aName)
|
||||
{
|
||||
ClearUserEntries(aName, NS_LITERAL_STRING("measure"));
|
||||
}
|
||||
|
||||
void
|
||||
Performance::LogEntry(PerformanceEntry* aEntry, const nsACString& aOwner) const
|
||||
{
|
||||
PERFLOG("Performance Entry: %s|%s|%s|%f|%f|%" PRIu64 "\n",
|
||||
aOwner.BeginReading(),
|
||||
NS_ConvertUTF16toUTF8(aEntry->GetEntryType()).get(),
|
||||
NS_ConvertUTF16toUTF8(aEntry->GetName()).get(),
|
||||
aEntry->StartTime(),
|
||||
aEntry->Duration(),
|
||||
static_cast<uint64_t>(PR_Now() / PR_USEC_PER_MSEC));
|
||||
}
|
||||
|
||||
void
|
||||
Performance::TimingNotification(PerformanceEntry* aEntry,
|
||||
const nsACString& aOwner, uint64_t aEpoch)
|
||||
{
|
||||
PerformanceEntryEventInit init;
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = false;
|
||||
init.mName = aEntry->GetName();
|
||||
init.mEntryType = aEntry->GetEntryType();
|
||||
init.mStartTime = aEntry->StartTime();
|
||||
init.mDuration = aEntry->Duration();
|
||||
init.mEpoch = aEpoch;
|
||||
init.mOrigin = NS_ConvertUTF8toUTF16(aOwner.BeginReading());
|
||||
|
||||
RefPtr<PerformanceEntryEvent> perfEntryEvent =
|
||||
PerformanceEntryEvent::Constructor(this, NS_LITERAL_STRING("performanceentry"), init);
|
||||
|
||||
nsCOMPtr<EventTarget> et = do_QueryInterface(GetOwner());
|
||||
if (et) {
|
||||
bool dummy = false;
|
||||
et->DispatchEvent(perfEntryEvent, &dummy);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Performance::InsertUserEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
mUserEntries.InsertElementSorted(aEntry,
|
||||
PerformanceEntryComparator());
|
||||
|
||||
QueueEntry(aEntry);
|
||||
}
|
||||
|
||||
void
|
||||
Performance::SetResourceTimingBufferSize(uint64_t aMaxSize)
|
||||
{
|
||||
mResourceTimingBufferSize = aMaxSize;
|
||||
}
|
||||
|
||||
void
|
||||
Performance::InsertResourceEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
MOZ_ASSERT(aEntry);
|
||||
MOZ_ASSERT(mResourceEntries.Length() < mResourceTimingBufferSize);
|
||||
if (mResourceEntries.Length() >= mResourceTimingBufferSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
mResourceEntries.InsertElementSorted(aEntry,
|
||||
PerformanceEntryComparator());
|
||||
if (mResourceEntries.Length() == mResourceTimingBufferSize) {
|
||||
// call onresourcetimingbufferfull
|
||||
DispatchBufferFullEvent();
|
||||
}
|
||||
QueueEntry(aEntry);
|
||||
}
|
||||
|
||||
void
|
||||
Performance::AddObserver(PerformanceObserver* aObserver)
|
||||
{
|
||||
mObservers.AppendElementUnlessExists(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
Performance::RemoveObserver(PerformanceObserver* aObserver)
|
||||
{
|
||||
mObservers.RemoveElement(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
Performance::NotifyObservers()
|
||||
{
|
||||
mPendingNotificationObserversTask = false;
|
||||
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
|
||||
PerformanceObserver,
|
||||
Notify, ());
|
||||
}
|
||||
|
||||
void
|
||||
Performance::CancelNotificationObservers()
|
||||
{
|
||||
mPendingNotificationObserversTask = false;
|
||||
}
|
||||
|
||||
class NotifyObserversTask final : public CancelableRunnable
|
||||
{
|
||||
public:
|
||||
explicit NotifyObserversTask(Performance* aPerformance)
|
||||
: mPerformance(aPerformance)
|
||||
{
|
||||
MOZ_ASSERT(mPerformance);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(mPerformance);
|
||||
mPerformance->NotifyObservers();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Cancel() override
|
||||
{
|
||||
mPerformance->CancelNotificationObservers();
|
||||
mPerformance = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~NotifyObserversTask()
|
||||
{
|
||||
}
|
||||
|
||||
RefPtr<Performance> mPerformance;
|
||||
};
|
||||
|
||||
void
|
||||
Performance::RunNotificationObserversTask()
|
||||
{
|
||||
mPendingNotificationObserversTask = true;
|
||||
nsCOMPtr<nsIRunnable> task = new NotifyObserversTask(this);
|
||||
nsresult rv = NS_DispatchToCurrentThread(task);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mPendingNotificationObserversTask = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Performance::QueueEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
if (mObservers.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
|
||||
PerformanceObserver,
|
||||
QueueEntry, (aEntry));
|
||||
|
||||
if (!mPendingNotificationObserversTask) {
|
||||
RunNotificationObserversTask();
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Performance::IsEnabled(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
return Preferences::GetBool("dom.enable_user_timing", false);
|
||||
}
|
||||
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<PrefEnabledRunnable> runnable =
|
||||
new PrefEnabledRunnable(workerPrivate,
|
||||
NS_LITERAL_CSTRING("dom.enable_user_timing"));
|
||||
return runnable->Dispatch() && runnable->IsEnabled();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Performance::IsObserverEnabled(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
return Preferences::GetBool("dom.enable_performance_observer", false);
|
||||
}
|
||||
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<PrefEnabledRunnable> runnable =
|
||||
new PrefEnabledRunnable(workerPrivate,
|
||||
NS_LITERAL_CSTRING("dom.enable_performance_observer"));
|
||||
|
||||
return runnable->Dispatch() && runnable->IsEnabled();
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
162
dom/performance/Performance.h
Normal file
162
dom/performance/Performance.h
Normal file
@ -0,0 +1,162 @@
|
||||
/* -*- 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_Performance_h
|
||||
#define mozilla_dom_Performance_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
|
||||
class nsITimedChannel;
|
||||
class nsIHttpChannel;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class PerformanceEntry;
|
||||
class PerformanceNavigation;
|
||||
class PerformanceObserver;
|
||||
class PerformanceTiming;
|
||||
|
||||
namespace workers {
|
||||
class WorkerPrivate;
|
||||
}
|
||||
|
||||
// Base class for main-thread and worker Performance API
|
||||
class Performance : public DOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Performance,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
static bool IsEnabled(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
static bool IsObserverEnabled(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
static already_AddRefed<Performance>
|
||||
CreateForMainThread(nsPIDOMWindowInner* aWindow,
|
||||
nsDOMNavigationTiming* aDOMTiming,
|
||||
nsITimedChannel* aChannel,
|
||||
Performance* aParentPerformance);
|
||||
|
||||
static already_AddRefed<Performance>
|
||||
CreateForWorker(workers::WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
JSObject* WrapObject(JSContext *cx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval);
|
||||
|
||||
void GetEntriesByType(const nsAString& aEntryType,
|
||||
nsTArray<RefPtr<PerformanceEntry>>& aRetval);
|
||||
|
||||
void GetEntriesByName(const nsAString& aName,
|
||||
const Optional<nsAString>& aEntryType,
|
||||
nsTArray<RefPtr<PerformanceEntry>>& aRetval);
|
||||
|
||||
virtual void AddEntry(nsIHttpChannel* channel,
|
||||
nsITimedChannel* timedChannel) = 0;
|
||||
|
||||
void ClearResourceTimings();
|
||||
|
||||
virtual DOMHighResTimeStamp Now() const = 0;
|
||||
|
||||
void Mark(const nsAString& aName, ErrorResult& aRv);
|
||||
|
||||
void ClearMarks(const Optional<nsAString>& aName);
|
||||
|
||||
void Measure(const nsAString& aName,
|
||||
const Optional<nsAString>& aStartMark,
|
||||
const Optional<nsAString>& aEndMark,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void ClearMeasures(const Optional<nsAString>& aName);
|
||||
|
||||
void SetResourceTimingBufferSize(uint64_t aMaxSize);
|
||||
|
||||
void AddObserver(PerformanceObserver* aObserver);
|
||||
void RemoveObserver(PerformanceObserver* aObserver);
|
||||
void NotifyObservers();
|
||||
void CancelNotificationObservers();
|
||||
|
||||
virtual PerformanceTiming* Timing() = 0;
|
||||
|
||||
virtual PerformanceNavigation* Navigation() = 0;
|
||||
|
||||
IMPL_EVENT_HANDLER(resourcetimingbufferfull)
|
||||
|
||||
virtual void GetMozMemory(JSContext *aCx,
|
||||
JS::MutableHandle<JSObject*> aObj) = 0;
|
||||
|
||||
virtual nsDOMNavigationTiming* GetDOMTiming() const = 0;
|
||||
|
||||
virtual nsITimedChannel* GetChannel() const = 0;
|
||||
|
||||
virtual Performance* GetParentPerformance() const = 0;
|
||||
|
||||
protected:
|
||||
Performance();
|
||||
explicit Performance(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
virtual ~Performance();
|
||||
|
||||
virtual void InsertUserEntry(PerformanceEntry* aEntry);
|
||||
void InsertResourceEntry(PerformanceEntry* aEntry);
|
||||
|
||||
void ClearUserEntries(const Optional<nsAString>& aEntryName,
|
||||
const nsAString& aEntryType);
|
||||
|
||||
DOMHighResTimeStamp ResolveTimestampFromName(const nsAString& aName,
|
||||
ErrorResult& aRv);
|
||||
|
||||
virtual nsISupports* GetAsISupports() = 0;
|
||||
|
||||
virtual void DispatchBufferFullEvent() = 0;
|
||||
|
||||
virtual TimeStamp CreationTimeStamp() const = 0;
|
||||
|
||||
virtual DOMHighResTimeStamp CreationTime() const = 0;
|
||||
|
||||
virtual bool IsPerformanceTimingAttribute(const nsAString& aName) = 0;
|
||||
|
||||
virtual DOMHighResTimeStamp
|
||||
GetPerformanceTimingFromString(const nsAString& aTimingName) = 0;
|
||||
|
||||
bool IsResourceEntryLimitReached() const
|
||||
{
|
||||
return mResourceEntries.Length() >= mResourceTimingBufferSize;
|
||||
}
|
||||
|
||||
void LogEntry(PerformanceEntry* aEntry, const nsACString& aOwner) const;
|
||||
void TimingNotification(PerformanceEntry* aEntry, const nsACString& aOwner,
|
||||
uint64_t epoch);
|
||||
|
||||
void RunNotificationObserversTask();
|
||||
void QueueEntry(PerformanceEntry* aEntry);
|
||||
|
||||
DOMHighResTimeStamp RoundTime(double aTime) const;
|
||||
|
||||
nsTObserverArray<PerformanceObserver*> mObservers;
|
||||
|
||||
private:
|
||||
nsTArray<RefPtr<PerformanceEntry>> mUserEntries;
|
||||
nsTArray<RefPtr<PerformanceEntry>> mResourceEntries;
|
||||
|
||||
uint64_t mResourceTimingBufferSize;
|
||||
static const uint64_t kDefaultResourceTimingBufferSize = 150;
|
||||
bool mPendingNotificationObserversTask;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_Performance_h
|
336
dom/performance/PerformanceMainThread.cpp
Normal file
336
dom/performance/PerformanceMainThread.cpp
Normal file
@ -0,0 +1,336 @@
|
||||
/* -*- 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 "PerformanceMainThread.h"
|
||||
#include "PerformanceNavigation.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceMainThread)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PerformanceMainThread,
|
||||
Performance)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTiming,
|
||||
mNavigation,
|
||||
mParentPerformance)
|
||||
tmp->mMozMemory = nullptr;
|
||||
mozilla::DropJSObjects(this);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PerformanceMainThread,
|
||||
Performance)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTiming,
|
||||
mNavigation,
|
||||
mParentPerformance)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceMainThread,
|
||||
Performance)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMozMemory)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(PerformanceMainThread, Performance)
|
||||
NS_IMPL_RELEASE_INHERITED(PerformanceMainThread, Performance)
|
||||
|
||||
// QueryInterface implementation for PerformanceMainThread
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceMainThread)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END_INHERITING(Performance)
|
||||
|
||||
PerformanceMainThread::PerformanceMainThread(nsPIDOMWindowInner* aWindow,
|
||||
nsDOMNavigationTiming* aDOMTiming,
|
||||
nsITimedChannel* aChannel,
|
||||
Performance* aParentPerformance)
|
||||
: Performance(aWindow)
|
||||
, mDOMTiming(aDOMTiming)
|
||||
, mChannel(aChannel)
|
||||
, mParentPerformance(aParentPerformance)
|
||||
{
|
||||
MOZ_ASSERT(aWindow, "Parent window object should be provided");
|
||||
}
|
||||
|
||||
PerformanceMainThread::~PerformanceMainThread()
|
||||
{
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceMainThread::GetMozMemory(JSContext *aCx,
|
||||
JS::MutableHandle<JSObject*> aObj)
|
||||
{
|
||||
if (!mMozMemory) {
|
||||
mMozMemory = js::gc::NewMemoryInfoObject(aCx);
|
||||
if (mMozMemory) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
}
|
||||
|
||||
aObj.set(mMozMemory);
|
||||
}
|
||||
|
||||
PerformanceTiming*
|
||||
PerformanceMainThread::Timing()
|
||||
{
|
||||
if (!mTiming) {
|
||||
// For navigation timing, the third argument (an nsIHtttpChannel) is null
|
||||
// since the cross-domain redirect were already checked. The last argument
|
||||
// (zero time) for performance.timing is the navigation start value.
|
||||
mTiming = new PerformanceTiming(this, mChannel, nullptr,
|
||||
mDOMTiming->GetNavigationStart());
|
||||
}
|
||||
|
||||
return mTiming;
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceMainThread::DispatchBufferFullEvent()
|
||||
{
|
||||
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
|
||||
// it bubbles, and it isn't cancelable
|
||||
event->InitEvent(NS_LITERAL_STRING("resourcetimingbufferfull"), true, false);
|
||||
event->SetTrusted(true);
|
||||
DispatchDOMEvent(nullptr, event, nullptr, nullptr);
|
||||
}
|
||||
|
||||
PerformanceNavigation*
|
||||
PerformanceMainThread::Navigation()
|
||||
{
|
||||
if (!mNavigation) {
|
||||
mNavigation = new PerformanceNavigation(this);
|
||||
}
|
||||
|
||||
return mNavigation;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
PerformanceMainThread::Now() const
|
||||
{
|
||||
return RoundTime(GetDOMTiming()->TimeStampToDOMHighRes(TimeStamp::Now()));
|
||||
}
|
||||
|
||||
/**
|
||||
* An entry should be added only after the resource is loaded.
|
||||
* This method is not thread safe and can only be called on the main thread.
|
||||
*/
|
||||
void
|
||||
PerformanceMainThread::AddEntry(nsIHttpChannel* channel,
|
||||
nsITimedChannel* timedChannel)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Check if resource timing is prefed off.
|
||||
if (!nsContentUtils::IsResourceTimingEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't add the entry if the buffer is full
|
||||
if (IsResourceEntryLimitReached()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (channel && timedChannel) {
|
||||
nsAutoCString name;
|
||||
nsAutoString initiatorType;
|
||||
nsCOMPtr<nsIURI> originalURI;
|
||||
|
||||
timedChannel->GetInitiatorType(initiatorType);
|
||||
|
||||
// According to the spec, "The name attribute must return the resolved URL
|
||||
// of the requested resource. This attribute must not change even if the
|
||||
// fetch redirected to a different URL."
|
||||
channel->GetOriginalURI(getter_AddRefs(originalURI));
|
||||
originalURI->GetSpec(name);
|
||||
NS_ConvertUTF8toUTF16 entryName(name);
|
||||
|
||||
// The nsITimedChannel argument will be used to gather all the timings.
|
||||
// The nsIHttpChannel argument will be used to check if any cross-origin
|
||||
// redirects occurred.
|
||||
// The last argument is the "zero time" (offset). Since we don't want
|
||||
// any offset for the resource timing, this will be set to "0" - the
|
||||
// resource timing returns a relative timing (no offset).
|
||||
RefPtr<PerformanceTiming> performanceTiming =
|
||||
new PerformanceTiming(this, timedChannel, channel,
|
||||
0);
|
||||
|
||||
// The PerformanceResourceTiming object will use the PerformanceTiming
|
||||
// object to get all the required timings.
|
||||
RefPtr<PerformanceResourceTiming> performanceEntry =
|
||||
new PerformanceResourceTiming(performanceTiming, this, entryName);
|
||||
|
||||
nsAutoCString protocol;
|
||||
channel->GetProtocolVersion(protocol);
|
||||
performanceEntry->SetNextHopProtocol(NS_ConvertUTF8toUTF16(protocol));
|
||||
|
||||
uint64_t encodedBodySize = 0;
|
||||
channel->GetEncodedBodySize(&encodedBodySize);
|
||||
performanceEntry->SetEncodedBodySize(encodedBodySize);
|
||||
|
||||
uint64_t transferSize = 0;
|
||||
channel->GetTransferSize(&transferSize);
|
||||
performanceEntry->SetTransferSize(transferSize);
|
||||
|
||||
uint64_t decodedBodySize = 0;
|
||||
channel->GetDecodedBodySize(&decodedBodySize);
|
||||
if (decodedBodySize == 0) {
|
||||
decodedBodySize = encodedBodySize;
|
||||
}
|
||||
performanceEntry->SetDecodedBodySize(decodedBodySize);
|
||||
|
||||
// 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);
|
||||
InsertResourceEntry(performanceEntry);
|
||||
}
|
||||
}
|
||||
|
||||
// To be removed once bug 1124165 lands
|
||||
bool
|
||||
PerformanceMainThread::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;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
PerformanceMainThread::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;
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceMainThread::InsertUserEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsAutoCString uri;
|
||||
uint64_t markCreationEpoch = 0;
|
||||
|
||||
if (nsContentUtils::IsUserTimingLoggingEnabled() ||
|
||||
nsContentUtils::SendPerformanceTimingNotifications()) {
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
|
||||
if (owner && owner->GetDocumentURI()) {
|
||||
rv = owner->GetDocumentURI()->GetHost(uri);
|
||||
}
|
||||
|
||||
if(NS_FAILED(rv)) {
|
||||
// If we have no URI, just put in "none".
|
||||
uri.AssignLiteral("none");
|
||||
}
|
||||
markCreationEpoch = static_cast<uint64_t>(PR_Now() / PR_USEC_PER_MSEC);
|
||||
|
||||
if (nsContentUtils::IsUserTimingLoggingEnabled()) {
|
||||
Performance::LogEntry(aEntry, uri);
|
||||
}
|
||||
}
|
||||
|
||||
if (nsContentUtils::SendPerformanceTimingNotifications()) {
|
||||
TimingNotification(aEntry, uri, markCreationEpoch);
|
||||
}
|
||||
|
||||
Performance::InsertUserEntry(aEntry);
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
PerformanceMainThread::CreationTimeStamp() const
|
||||
{
|
||||
return GetDOMTiming()->GetNavigationStartTimeStamp();
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
PerformanceMainThread::CreationTime() const
|
||||
{
|
||||
return GetDOMTiming()->GetNavigationStart();
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
87
dom/performance/PerformanceMainThread.h
Normal file
87
dom/performance/PerformanceMainThread.h
Normal file
@ -0,0 +1,87 @@
|
||||
/* -*- 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_PerformanceMainThread_h
|
||||
#define mozilla_dom_PerformanceMainThread_h
|
||||
|
||||
#include "Performance.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class PerformanceMainThread final : public Performance
|
||||
{
|
||||
public:
|
||||
PerformanceMainThread(nsPIDOMWindowInner* aWindow,
|
||||
nsDOMNavigationTiming* aDOMTiming,
|
||||
nsITimedChannel* aChannel,
|
||||
Performance* aParentPerformance);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PerformanceMainThread,
|
||||
Performance)
|
||||
|
||||
// Performance WebIDL methods
|
||||
DOMHighResTimeStamp Now() const override;
|
||||
|
||||
virtual PerformanceTiming* Timing() override;
|
||||
|
||||
virtual PerformanceNavigation* Navigation() override;
|
||||
|
||||
virtual void AddEntry(nsIHttpChannel* channel,
|
||||
nsITimedChannel* timedChannel) override;
|
||||
|
||||
TimeStamp CreationTimeStamp() const override;
|
||||
|
||||
DOMHighResTimeStamp CreationTime() const override;
|
||||
|
||||
virtual void GetMozMemory(JSContext *aCx,
|
||||
JS::MutableHandle<JSObject*> aObj) override;
|
||||
|
||||
virtual nsDOMNavigationTiming* GetDOMTiming() const override
|
||||
{
|
||||
return mDOMTiming;
|
||||
}
|
||||
|
||||
virtual nsITimedChannel* GetChannel() const override
|
||||
{
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
virtual Performance* GetParentPerformance() const override
|
||||
{
|
||||
return mParentPerformance;
|
||||
}
|
||||
|
||||
protected:
|
||||
~PerformanceMainThread();
|
||||
|
||||
nsISupports* GetAsISupports() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void InsertUserEntry(PerformanceEntry* aEntry) override;
|
||||
|
||||
bool IsPerformanceTimingAttribute(const nsAString& aName) override;
|
||||
|
||||
DOMHighResTimeStamp
|
||||
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
|
||||
|
||||
void DispatchBufferFullEvent() override;
|
||||
|
||||
RefPtr<nsDOMNavigationTiming> mDOMTiming;
|
||||
nsCOMPtr<nsITimedChannel> mChannel;
|
||||
RefPtr<PerformanceTiming> mTiming;
|
||||
RefPtr<PerformanceNavigation> mNavigation;
|
||||
RefPtr<Performance> mParentPerformance;
|
||||
JS::Heap<JSObject*> mMozMemory;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PerformanceMainThread_h
|
@ -16,7 +16,7 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PerformanceNavigation, mPerformance)
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PerformanceNavigation, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PerformanceNavigation, Release)
|
||||
|
||||
PerformanceNavigation::PerformanceNavigation(nsPerformance* aPerformance)
|
||||
PerformanceNavigation::PerformanceNavigation(Performance* aPerformance)
|
||||
: mPerformance(aPerformance)
|
||||
{
|
||||
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
|
||||
|
@ -8,8 +8,8 @@
|
||||
#define mozilla_dom_PerformanceNavigation_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -26,7 +26,7 @@ public:
|
||||
TYPE_RESERVED = 255,
|
||||
};
|
||||
|
||||
explicit PerformanceNavigation(nsPerformance* aPerformance);
|
||||
explicit PerformanceNavigation(Performance* aPerformance);
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PerformanceNavigation)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(PerformanceNavigation)
|
||||
@ -41,7 +41,7 @@ public:
|
||||
return mPerformance->Timing();
|
||||
}
|
||||
|
||||
nsPerformance* GetParentObject() const
|
||||
Performance* GetParentObject() const
|
||||
{
|
||||
return mPerformance;
|
||||
}
|
||||
@ -59,7 +59,7 @@ public:
|
||||
|
||||
private:
|
||||
~PerformanceNavigation();
|
||||
RefPtr<nsPerformance> mPerformance;
|
||||
RefPtr<Performance> mPerformance;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -6,11 +6,10 @@
|
||||
|
||||
#include "PerformanceObserver.h"
|
||||
|
||||
#include "mozilla/dom/Performance.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"
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsPIDOMWindowInner;
|
||||
class PerformanceBase;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -24,6 +23,7 @@ class ErrorResult;
|
||||
namespace dom {
|
||||
|
||||
class GlobalObject;
|
||||
class Performance;
|
||||
class PerformanceEntry;
|
||||
class PerformanceObserverCallback;
|
||||
struct PerformanceObserverInit;
|
||||
@ -67,7 +67,7 @@ private:
|
||||
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
RefPtr<PerformanceObserverCallback> mCallback;
|
||||
RefPtr<PerformanceBase> mPerformance;
|
||||
RefPtr<Performance> mPerformance;
|
||||
nsTArray<nsString> mEntryTypes;
|
||||
bool mConnected;
|
||||
nsTArray<RefPtr<PerformanceEntry>> mQueuedEntries;
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
#include "PerformanceObserverEntryList.h"
|
||||
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/PerformanceObserverEntryListBinding.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsString.h"
|
||||
#include "PerformanceResourceTiming.h"
|
||||
|
||||
|
@ -24,7 +24,7 @@ NS_IMPL_ADDREF_INHERITED(PerformanceResourceTiming, PerformanceEntry)
|
||||
NS_IMPL_RELEASE_INHERITED(PerformanceResourceTiming, PerformanceEntry)
|
||||
|
||||
PerformanceResourceTiming::PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming,
|
||||
nsPerformance* aPerformance,
|
||||
Performance* aPerformance,
|
||||
const nsAString& aName)
|
||||
: PerformanceEntry(aPerformance, aName, NS_LITERAL_STRING("resource")),
|
||||
mTiming(aPerformanceTiming),
|
||||
|
@ -8,10 +8,9 @@
|
||||
#define mozilla_dom_PerformanceResourceTiming_h___
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#include "Performance.h"
|
||||
#include "PerformanceEntry.h"
|
||||
#include "PerformanceTiming.h"
|
||||
|
||||
@ -30,7 +29,7 @@ public:
|
||||
PerformanceEntry)
|
||||
|
||||
PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming,
|
||||
nsPerformance* aPerformance,
|
||||
Performance* aPerformance,
|
||||
const nsAString& aName);
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
@ -15,7 +15,7 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PerformanceTiming, mPerformance)
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PerformanceTiming, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PerformanceTiming, Release)
|
||||
|
||||
PerformanceTiming::PerformanceTiming(nsPerformance* aPerformance,
|
||||
PerformanceTiming::PerformanceTiming(Performance* aPerformance,
|
||||
nsITimedChannel* aChannel,
|
||||
nsIHttpChannel* aHttpChannel,
|
||||
DOMHighResTimeStamp aZeroTime)
|
||||
|
@ -10,8 +10,8 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "Performance.h"
|
||||
|
||||
class nsIHttpChannel;
|
||||
class nsITimedChannel;
|
||||
@ -42,7 +42,7 @@ public:
|
||||
* argument should be equal to performance.navigationStart for
|
||||
* navigation timing and "0" for the resource timing.
|
||||
*/
|
||||
PerformanceTiming(nsPerformance* aPerformance,
|
||||
PerformanceTiming(Performance* aPerformance,
|
||||
nsITimedChannel* aChannel,
|
||||
nsIHttpChannel* aHttpChannel,
|
||||
DOMHighResTimeStamp aZeroTime);
|
||||
@ -54,7 +54,7 @@ public:
|
||||
return mPerformance->GetDOMTiming();
|
||||
}
|
||||
|
||||
nsPerformance* GetParentObject() const
|
||||
Performance* GetParentObject() const
|
||||
{
|
||||
return mPerformance;
|
||||
}
|
||||
@ -240,7 +240,7 @@ private:
|
||||
bool IsInitialized() const;
|
||||
void InitializeTimingInfo(nsITimedChannel* aChannel);
|
||||
|
||||
RefPtr<nsPerformance> mPerformance;
|
||||
RefPtr<Performance> mPerformance;
|
||||
DOMHighResTimeStamp mFetchStart;
|
||||
|
||||
// This is an offset that will be added to each timing ([ms] resolution).
|
||||
|
@ -4,32 +4,27 @@
|
||||
* 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 "Performance.h"
|
||||
#include "mozilla/dom/PerformanceBinding.h"
|
||||
|
||||
#include "PerformanceWorker.h"
|
||||
#include "WorkerPrivate.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
Performance::Performance(WorkerPrivate* aWorkerPrivate)
|
||||
using namespace workers;
|
||||
|
||||
PerformanceWorker::PerformanceWorker(WorkerPrivate* aWorkerPrivate)
|
||||
: mWorkerPrivate(aWorkerPrivate)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
Performance::~Performance()
|
||||
PerformanceWorker::~PerformanceWorker()
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Performance::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return PerformanceBinding_workers::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
Performance::Now() const
|
||||
PerformanceWorker::Now() const
|
||||
{
|
||||
TimeDuration duration =
|
||||
TimeStamp::Now() - mWorkerPrivate->NowBaseTimeStamp();
|
||||
@ -38,14 +33,14 @@ Performance::Now() const
|
||||
|
||||
// To be removed once bug 1124165 lands
|
||||
bool
|
||||
Performance::IsPerformanceTimingAttribute(const nsAString& aName)
|
||||
PerformanceWorker::IsPerformanceTimingAttribute(const nsAString& aName)
|
||||
{
|
||||
// In workers we just support navigationStart.
|
||||
return aName.EqualsASCII("navigationStart");
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
Performance::GetPerformanceTimingFromString(const nsAString& aProperty)
|
||||
PerformanceWorker::GetPerformanceTimingFromString(const nsAString& aProperty)
|
||||
{
|
||||
if (!IsPerformanceTimingAttribute(aProperty)) {
|
||||
return 0;
|
||||
@ -60,7 +55,7 @@ Performance::GetPerformanceTimingFromString(const nsAString& aProperty)
|
||||
}
|
||||
|
||||
void
|
||||
Performance::InsertUserEntry(PerformanceEntry* aEntry)
|
||||
PerformanceWorker::InsertUserEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
if (mWorkerPrivate->PerformanceLoggingEnabled()) {
|
||||
nsAutoCString uri;
|
||||
@ -69,29 +64,22 @@ Performance::InsertUserEntry(PerformanceEntry* aEntry)
|
||||
// If we have no URI, just put in "none".
|
||||
uri.AssignLiteral("none");
|
||||
}
|
||||
PerformanceBase::LogEntry(aEntry, uri);
|
||||
Performance::LogEntry(aEntry, uri);
|
||||
}
|
||||
PerformanceBase::InsertUserEntry(aEntry);
|
||||
Performance::InsertUserEntry(aEntry);
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
Performance::CreationTimeStamp() const
|
||||
PerformanceWorker::CreationTimeStamp() const
|
||||
{
|
||||
return mWorkerPrivate->NowBaseTimeStamp();
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
Performance::CreationTime() const
|
||||
PerformanceWorker::CreationTime() const
|
||||
{
|
||||
return mWorkerPrivate->NowBaseTime();
|
||||
}
|
||||
|
||||
void
|
||||
Performance::DispatchBufferFullEvent()
|
||||
{
|
||||
// This method is needed just for InsertResourceEntry, but this method is not
|
||||
// exposed to workers.
|
||||
MOZ_CRASH("This should not be called.");
|
||||
}
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
100
dom/performance/PerformanceWorker.h
Normal file
100
dom/performance/PerformanceWorker.h
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/. */
|
||||
|
||||
#ifndef mozilla_dom_PerformanceWorker_h
|
||||
#define mozilla_dom_PerformanceWorker_h
|
||||
|
||||
#include "Performance.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace workers {
|
||||
class WorkerPrivate;
|
||||
}
|
||||
|
||||
class PerformanceWorker final : public Performance
|
||||
{
|
||||
public:
|
||||
PerformanceWorker(workers::WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
// Performance WebIDL methods
|
||||
DOMHighResTimeStamp Now() const override;
|
||||
|
||||
virtual PerformanceTiming* Timing() override
|
||||
{
|
||||
MOZ_CRASH("This should not be called on workers.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual PerformanceNavigation* Navigation() override
|
||||
{
|
||||
MOZ_CRASH("This should not be called on workers.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void AddEntry(nsIHttpChannel* channel,
|
||||
nsITimedChannel* timedChannel) override
|
||||
{
|
||||
MOZ_CRASH("This should not be called on workers.");
|
||||
}
|
||||
|
||||
TimeStamp CreationTimeStamp() const override;
|
||||
|
||||
DOMHighResTimeStamp CreationTime() const override;
|
||||
|
||||
virtual void GetMozMemory(JSContext *aCx,
|
||||
JS::MutableHandle<JSObject*> aObj) override
|
||||
{
|
||||
MOZ_CRASH("This should not be called on workers.");
|
||||
}
|
||||
|
||||
virtual nsDOMNavigationTiming* GetDOMTiming() const override
|
||||
{
|
||||
MOZ_CRASH("This should not be called on workers.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual nsITimedChannel* GetChannel() const override
|
||||
{
|
||||
MOZ_CRASH("This should not be called on workers.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual Performance* GetParentPerformance() const override
|
||||
{
|
||||
MOZ_CRASH("This should not be called on workers.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
~PerformanceWorker();
|
||||
|
||||
nsISupports* GetAsISupports() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void InsertUserEntry(PerformanceEntry* aEntry) override;
|
||||
|
||||
bool IsPerformanceTimingAttribute(const nsAString& aName) override;
|
||||
|
||||
DOMHighResTimeStamp
|
||||
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
|
||||
|
||||
void DispatchBufferFullEvent() override
|
||||
{
|
||||
MOZ_CRASH("This should not be called on workers.");
|
||||
}
|
||||
|
||||
private:
|
||||
workers::WorkerPrivate* mWorkerPrivate;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PerformanceWorker_h
|
@ -4,11 +4,8 @@
|
||||
# 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/.
|
||||
|
||||
EXPORTS += [
|
||||
'nsPerformance.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Performance.h',
|
||||
'PerformanceEntry.h',
|
||||
'PerformanceMark.h',
|
||||
'PerformanceMeasure.h',
|
||||
@ -20,8 +17,9 @@ EXPORTS.mozilla.dom += [
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nsPerformance.cpp',
|
||||
'Performance.cpp',
|
||||
'PerformanceEntry.cpp',
|
||||
'PerformanceMainThread.cpp',
|
||||
'PerformanceMark.cpp',
|
||||
'PerformanceMeasure.cpp',
|
||||
'PerformanceNavigation.cpp',
|
||||
@ -29,6 +27,7 @@ UNIFIED_SOURCES += [
|
||||
'PerformanceObserverEntryList.cpp',
|
||||
'PerformanceResourceTiming.cpp',
|
||||
'PerformanceTiming.cpp',
|
||||
'PerformanceWorker.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
|
@ -1,833 +0,0 @@
|
||||
/* -*- 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 "nsPerformance.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#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 "PerformanceObserver.h"
|
||||
#include "PerformanceResourceTiming.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/PerformanceBinding.h"
|
||||
#include "mozilla/dom/PerformanceEntryEvent.h"
|
||||
#include "mozilla/dom/PerformanceNavigationBinding.h"
|
||||
#include "mozilla/dom/PerformanceObserverBinding.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "js/HeapAPI.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#define PERFLOG(msg, ...) __android_log_print(ANDROID_LOG_INFO, "PerformanceTiming", msg, ##__VA_ARGS__)
|
||||
#else
|
||||
#define PERFLOG(msg, ...) printf_stderr(msg, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::workers;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsPerformance)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsPerformance, PerformanceBase)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTiming,
|
||||
mNavigation,
|
||||
mParentPerformance)
|
||||
tmp->mMozMemory = nullptr;
|
||||
mozilla::DropJSObjects(this);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsPerformance, PerformanceBase)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTiming,
|
||||
mNavigation,
|
||||
mParentPerformance)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsPerformance, PerformanceBase)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMozMemory)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsPerformance, PerformanceBase)
|
||||
NS_IMPL_RELEASE_INHERITED(nsPerformance, PerformanceBase)
|
||||
|
||||
nsPerformance::nsPerformance(nsPIDOMWindowInner* aWindow,
|
||||
nsDOMNavigationTiming* aDOMTiming,
|
||||
nsITimedChannel* aChannel,
|
||||
nsPerformance* aParentPerformance)
|
||||
: PerformanceBase(aWindow),
|
||||
mDOMTiming(aDOMTiming),
|
||||
mChannel(aChannel),
|
||||
mParentPerformance(aParentPerformance)
|
||||
{
|
||||
MOZ_ASSERT(aWindow, "Parent window object should be provided");
|
||||
}
|
||||
|
||||
nsPerformance::~nsPerformance()
|
||||
{
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
// QueryInterface implementation for nsPerformance
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPerformance)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
void
|
||||
nsPerformance::GetMozMemory(JSContext *aCx, JS::MutableHandle<JSObject*> aObj)
|
||||
{
|
||||
if (!mMozMemory) {
|
||||
mMozMemory = js::gc::NewMemoryInfoObject(aCx);
|
||||
if (mMozMemory) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
}
|
||||
|
||||
aObj.set(mMozMemory);
|
||||
}
|
||||
|
||||
PerformanceTiming*
|
||||
nsPerformance::Timing()
|
||||
{
|
||||
if (!mTiming) {
|
||||
// For navigation timing, the third argument (an nsIHtttpChannel) is null
|
||||
// since the cross-domain redirect were already checked.
|
||||
// The last argument (zero time) for performance.timing is the navigation
|
||||
// start value.
|
||||
mTiming = new PerformanceTiming(this, mChannel, nullptr,
|
||||
mDOMTiming->GetNavigationStart());
|
||||
}
|
||||
return mTiming;
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::DispatchBufferFullEvent()
|
||||
{
|
||||
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
|
||||
// it bubbles, and it isn't cancelable
|
||||
event->InitEvent(NS_LITERAL_STRING("resourcetimingbufferfull"), true, false);
|
||||
event->SetTrusted(true);
|
||||
DispatchDOMEvent(nullptr, event, nullptr, nullptr);
|
||||
}
|
||||
|
||||
PerformanceNavigation*
|
||||
nsPerformance::Navigation()
|
||||
{
|
||||
if (!mNavigation) {
|
||||
mNavigation = new PerformanceNavigation(this);
|
||||
}
|
||||
return mNavigation;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
nsPerformance::Now() const
|
||||
{
|
||||
return RoundTime(GetDOMTiming()->TimeStampToDOMHighRes(TimeStamp::Now()));
|
||||
}
|
||||
|
||||
JSObject*
|
||||
nsPerformance::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return PerformanceBinding::Wrap(cx, this, aGivenProto);
|
||||
}
|
||||
|
||||
/**
|
||||
* An entry should be added only after the resource is loaded.
|
||||
* This method is not thread safe and can only be called on the main thread.
|
||||
*/
|
||||
void
|
||||
nsPerformance::AddEntry(nsIHttpChannel* channel,
|
||||
nsITimedChannel* timedChannel)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// Check if resource timing is prefed off.
|
||||
if (!nsContentUtils::IsResourceTimingEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't add the entry if the buffer is full
|
||||
if (IsResourceEntryLimitReached()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (channel && timedChannel) {
|
||||
nsAutoCString name;
|
||||
nsAutoString initiatorType;
|
||||
nsCOMPtr<nsIURI> originalURI;
|
||||
|
||||
timedChannel->GetInitiatorType(initiatorType);
|
||||
|
||||
// According to the spec, "The name attribute must return the resolved URL
|
||||
// of the requested resource. This attribute must not change even if the
|
||||
// fetch redirected to a different URL."
|
||||
channel->GetOriginalURI(getter_AddRefs(originalURI));
|
||||
originalURI->GetSpec(name);
|
||||
NS_ConvertUTF8toUTF16 entryName(name);
|
||||
|
||||
// The nsITimedChannel argument will be used to gather all the timings.
|
||||
// The nsIHttpChannel argument will be used to check if any cross-origin
|
||||
// redirects occurred.
|
||||
// The last argument is the "zero time" (offset). Since we don't want
|
||||
// any offset for the resource timing, this will be set to "0" - the
|
||||
// resource timing returns a relative timing (no offset).
|
||||
RefPtr<PerformanceTiming> performanceTiming =
|
||||
new PerformanceTiming(this, timedChannel, channel,
|
||||
0);
|
||||
|
||||
// The PerformanceResourceTiming object will use the PerformanceTiming
|
||||
// object to get all the required timings.
|
||||
RefPtr<PerformanceResourceTiming> performanceEntry =
|
||||
new PerformanceResourceTiming(performanceTiming, this, entryName);
|
||||
|
||||
nsAutoCString protocol;
|
||||
channel->GetProtocolVersion(protocol);
|
||||
performanceEntry->SetNextHopProtocol(NS_ConvertUTF8toUTF16(protocol));
|
||||
|
||||
uint64_t encodedBodySize = 0;
|
||||
channel->GetEncodedBodySize(&encodedBodySize);
|
||||
performanceEntry->SetEncodedBodySize(encodedBodySize);
|
||||
|
||||
uint64_t transferSize = 0;
|
||||
channel->GetTransferSize(&transferSize);
|
||||
performanceEntry->SetTransferSize(transferSize);
|
||||
|
||||
uint64_t decodedBodySize = 0;
|
||||
channel->GetDecodedBodySize(&decodedBodySize);
|
||||
if (decodedBodySize == 0) {
|
||||
decodedBodySize = encodedBodySize;
|
||||
}
|
||||
performanceEntry->SetDecodedBodySize(decodedBodySize);
|
||||
|
||||
// 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);
|
||||
InsertResourceEntry(performanceEntry);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
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;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Helper classes
|
||||
class MOZ_STACK_CLASS PerformanceEntryComparator final
|
||||
{
|
||||
public:
|
||||
bool Equals(const PerformanceEntry* aElem1,
|
||||
const PerformanceEntry* aElem2) const
|
||||
{
|
||||
MOZ_ASSERT(aElem1 && aElem2,
|
||||
"Trying to compare null performance entries");
|
||||
return aElem1->StartTime() == aElem2->StartTime();
|
||||
}
|
||||
|
||||
bool LessThan(const PerformanceEntry* aElem1,
|
||||
const PerformanceEntry* aElem2) const
|
||||
{
|
||||
MOZ_ASSERT(aElem1 && aElem2,
|
||||
"Trying to compare null performance entries");
|
||||
return aElem1->StartTime() < aElem2->StartTime();
|
||||
}
|
||||
};
|
||||
|
||||
class PrefEnabledRunnable final : public WorkerCheckAPIExposureOnMainThreadRunnable
|
||||
{
|
||||
public:
|
||||
PrefEnabledRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsCString& aPrefName)
|
||||
: WorkerCheckAPIExposureOnMainThreadRunnable(aWorkerPrivate)
|
||||
, mEnabled(false)
|
||||
, mPrefName(aPrefName)
|
||||
{ }
|
||||
|
||||
bool MainThreadRun() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mEnabled = Preferences::GetBool(mPrefName.get(), false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsEnabled() const
|
||||
{
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mEnabled;
|
||||
nsCString mPrefName;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
/* static */ bool
|
||||
nsPerformance::IsEnabled(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
return Preferences::GetBool("dom.enable_user_timing", false);
|
||||
}
|
||||
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<PrefEnabledRunnable> runnable =
|
||||
new PrefEnabledRunnable(workerPrivate,
|
||||
NS_LITERAL_CSTRING("dom.enable_user_timing"));
|
||||
return runnable->Dispatch() && 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();
|
||||
|
||||
RefPtr<PrefEnabledRunnable> runnable =
|
||||
new PrefEnabledRunnable(workerPrivate,
|
||||
NS_LITERAL_CSTRING("dom.enable_performance_observer"));
|
||||
|
||||
return runnable->Dispatch() && runnable->IsEnabled();
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::InsertUserEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsAutoCString uri;
|
||||
uint64_t markCreationEpoch = 0;
|
||||
|
||||
if (nsContentUtils::IsUserTimingLoggingEnabled() ||
|
||||
nsContentUtils::SendPerformanceTimingNotifications()) {
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
|
||||
if (owner && owner->GetDocumentURI()) {
|
||||
rv = owner->GetDocumentURI()->GetHost(uri);
|
||||
}
|
||||
|
||||
if(NS_FAILED(rv)) {
|
||||
// If we have no URI, just put in "none".
|
||||
uri.AssignLiteral("none");
|
||||
}
|
||||
markCreationEpoch = static_cast<uint64_t>(PR_Now() / PR_USEC_PER_MSEC);
|
||||
|
||||
if (nsContentUtils::IsUserTimingLoggingEnabled()) {
|
||||
PerformanceBase::LogEntry(aEntry, uri);
|
||||
}
|
||||
}
|
||||
|
||||
if (nsContentUtils::SendPerformanceTimingNotifications()) {
|
||||
TimingNotification(aEntry, uri, markCreationEpoch);
|
||||
}
|
||||
|
||||
PerformanceBase::InsertUserEntry(aEntry);
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
nsPerformance::CreationTimeStamp() const
|
||||
{
|
||||
return GetDOMTiming()->GetNavigationStartTimeStamp();
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
nsPerformance::CreationTime() const
|
||||
{
|
||||
return GetDOMTiming()->GetNavigationStart();
|
||||
}
|
||||
|
||||
// PerformanceBase
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PerformanceBase)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformanceBase,
|
||||
DOMEventTargetHelper,
|
||||
mUserEntries,
|
||||
mResourceEntries);
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(PerformanceBase, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(PerformanceBase, DOMEventTargetHelper)
|
||||
|
||||
PerformanceBase::PerformanceBase()
|
||||
: mResourceTimingBufferSize(kDefaultResourceTimingBufferSize)
|
||||
, mPendingNotificationObserversTask(false)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
}
|
||||
|
||||
PerformanceBase::PerformanceBase(nsPIDOMWindowInner* aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mResourceTimingBufferSize(kDefaultResourceTimingBufferSize)
|
||||
, mPendingNotificationObserversTask(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
PerformanceBase::~PerformanceBase()
|
||||
{}
|
||||
|
||||
void
|
||||
PerformanceBase::GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval)
|
||||
{
|
||||
aRetval = mResourceEntries;
|
||||
aRetval.AppendElements(mUserEntries);
|
||||
aRetval.Sort(PerformanceEntryComparator());
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::GetEntriesByType(const nsAString& aEntryType,
|
||||
nsTArray<RefPtr<PerformanceEntry>>& aRetval)
|
||||
{
|
||||
if (aEntryType.EqualsLiteral("resource")) {
|
||||
aRetval = mResourceEntries;
|
||||
return;
|
||||
}
|
||||
|
||||
aRetval.Clear();
|
||||
|
||||
if (aEntryType.EqualsLiteral("mark") ||
|
||||
aEntryType.EqualsLiteral("measure")) {
|
||||
for (PerformanceEntry* entry : mUserEntries) {
|
||||
if (entry->GetEntryType().Equals(aEntryType)) {
|
||||
aRetval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::GetEntriesByName(const nsAString& aName,
|
||||
const Optional<nsAString>& aEntryType,
|
||||
nsTArray<RefPtr<PerformanceEntry>>& aRetval)
|
||||
{
|
||||
aRetval.Clear();
|
||||
|
||||
for (PerformanceEntry* entry : mResourceEntries) {
|
||||
if (entry->GetName().Equals(aName) &&
|
||||
(!aEntryType.WasPassed() ||
|
||||
entry->GetEntryType().Equals(aEntryType.Value()))) {
|
||||
aRetval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
|
||||
for (PerformanceEntry* entry : mUserEntries) {
|
||||
if (entry->GetName().Equals(aName) &&
|
||||
(!aEntryType.WasPassed() ||
|
||||
entry->GetEntryType().Equals(aEntryType.Value()))) {
|
||||
aRetval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
|
||||
aRetval.Sort(PerformanceEntryComparator());
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::ClearUserEntries(const Optional<nsAString>& aEntryName,
|
||||
const nsAString& aEntryType)
|
||||
{
|
||||
for (uint32_t i = 0; i < mUserEntries.Length();) {
|
||||
if ((!aEntryName.WasPassed() ||
|
||||
mUserEntries[i]->GetName().Equals(aEntryName.Value())) &&
|
||||
(aEntryType.IsEmpty() ||
|
||||
mUserEntries[i]->GetEntryType().Equals(aEntryType))) {
|
||||
mUserEntries.RemoveElementAt(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::ClearResourceTimings()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mResourceEntries.Clear();
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
PerformanceBase::RoundTime(double aTime) const
|
||||
{
|
||||
// Round down to the nearest 5us, because if the timer is too accurate people
|
||||
// can do nasty timing attacks with it. See similar code in the worker
|
||||
// Performance implementation.
|
||||
const double maxResolutionMs = 0.005;
|
||||
return floor(aTime / maxResolutionMs) * maxResolutionMs;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PerformanceBase::Mark(const nsAString& aName, ErrorResult& aRv)
|
||||
{
|
||||
// Don't add the entry if the buffer is full. XXX should be removed by bug 1159003.
|
||||
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsPerformanceTimingAttribute(aName)) {
|
||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<PerformanceMark> performanceMark =
|
||||
new PerformanceMark(GetAsISupports(), aName, Now());
|
||||
InsertUserEntry(performanceMark);
|
||||
|
||||
if (profiler_is_active()) {
|
||||
PROFILER_MARKER(NS_ConvertUTF16toUTF8(aName).get());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::ClearMarks(const Optional<nsAString>& aName)
|
||||
{
|
||||
ClearUserEntries(aName, NS_LITERAL_STRING("mark"));
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
PerformanceBase::ResolveTimestampFromName(const nsAString& aName,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AutoTArray<RefPtr<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 ts - CreationTime();
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::Measure(const nsAString& aName,
|
||||
const Optional<nsAString>& aStartMark,
|
||||
const Optional<nsAString>& aEndMark,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// Don't add the entry if the buffer is full. XXX should be removed by bug
|
||||
// 1159003.
|
||||
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
|
||||
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();
|
||||
}
|
||||
|
||||
RefPtr<PerformanceMeasure> performanceMeasure =
|
||||
new PerformanceMeasure(GetAsISupports(), aName, startTime, endTime);
|
||||
InsertUserEntry(performanceMeasure);
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::ClearMeasures(const Optional<nsAString>& aName)
|
||||
{
|
||||
ClearUserEntries(aName, NS_LITERAL_STRING("measure"));
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::LogEntry(PerformanceEntry* aEntry, const nsACString& aOwner) const
|
||||
{
|
||||
PERFLOG("Performance Entry: %s|%s|%s|%f|%f|%" PRIu64 "\n",
|
||||
aOwner.BeginReading(),
|
||||
NS_ConvertUTF16toUTF8(aEntry->GetEntryType()).get(),
|
||||
NS_ConvertUTF16toUTF8(aEntry->GetName()).get(),
|
||||
aEntry->StartTime(),
|
||||
aEntry->Duration(),
|
||||
static_cast<uint64_t>(PR_Now() / PR_USEC_PER_MSEC));
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::TimingNotification(PerformanceEntry* aEntry, const nsACString& aOwner, uint64_t aEpoch)
|
||||
{
|
||||
PerformanceEntryEventInit init;
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = false;
|
||||
init.mName = aEntry->GetName();
|
||||
init.mEntryType = aEntry->GetEntryType();
|
||||
init.mStartTime = aEntry->StartTime();
|
||||
init.mDuration = aEntry->Duration();
|
||||
init.mEpoch = aEpoch;
|
||||
init.mOrigin = NS_ConvertUTF8toUTF16(aOwner.BeginReading());
|
||||
|
||||
RefPtr<PerformanceEntryEvent> perfEntryEvent =
|
||||
PerformanceEntryEvent::Constructor(this, NS_LITERAL_STRING("performanceentry"), init);
|
||||
|
||||
nsCOMPtr<EventTarget> et = do_QueryInterface(GetOwner());
|
||||
if (et) {
|
||||
bool dummy = false;
|
||||
et->DispatchEvent(perfEntryEvent, &dummy);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::InsertUserEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
mUserEntries.InsertElementSorted(aEntry,
|
||||
PerformanceEntryComparator());
|
||||
|
||||
QueueEntry(aEntry);
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::SetResourceTimingBufferSize(uint64_t aMaxSize)
|
||||
{
|
||||
mResourceTimingBufferSize = aMaxSize;
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::InsertResourceEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
MOZ_ASSERT(aEntry);
|
||||
MOZ_ASSERT(mResourceEntries.Length() < mResourceTimingBufferSize);
|
||||
if (mResourceEntries.Length() >= mResourceTimingBufferSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
mResourceEntries.InsertElementSorted(aEntry,
|
||||
PerformanceEntryComparator());
|
||||
if (mResourceEntries.Length() == mResourceTimingBufferSize) {
|
||||
// call onresourcetimingbufferfull
|
||||
DispatchBufferFullEvent();
|
||||
}
|
||||
QueueEntry(aEntry);
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::AddObserver(PerformanceObserver* aObserver)
|
||||
{
|
||||
mObservers.AppendElementUnlessExists(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::RemoveObserver(PerformanceObserver* aObserver)
|
||||
{
|
||||
mObservers.RemoveElement(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::NotifyObservers()
|
||||
{
|
||||
mPendingNotificationObserversTask = false;
|
||||
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
|
||||
PerformanceObserver,
|
||||
Notify, ());
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::CancelNotificationObservers()
|
||||
{
|
||||
mPendingNotificationObserversTask = false;
|
||||
}
|
||||
|
||||
class NotifyObserversTask final : public CancelableRunnable
|
||||
{
|
||||
public:
|
||||
explicit NotifyObserversTask(PerformanceBase* aPerformance)
|
||||
: mPerformance(aPerformance)
|
||||
{
|
||||
MOZ_ASSERT(mPerformance);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(mPerformance);
|
||||
mPerformance->NotifyObservers();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Cancel() override
|
||||
{
|
||||
mPerformance->CancelNotificationObservers();
|
||||
mPerformance = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~NotifyObserversTask()
|
||||
{
|
||||
}
|
||||
|
||||
RefPtr<PerformanceBase> mPerformance;
|
||||
};
|
||||
|
||||
void
|
||||
PerformanceBase::RunNotificationObserversTask()
|
||||
{
|
||||
mPendingNotificationObserversTask = true;
|
||||
nsCOMPtr<nsIRunnable> task = new NotifyObserversTask(this);
|
||||
nsresult rv = NS_DispatchToCurrentThread(task);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mPendingNotificationObserversTask = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PerformanceBase::QueueEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
if (mObservers.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
|
||||
PerformanceObserver,
|
||||
QueueEntry, (aEntry));
|
||||
|
||||
if (!mPendingNotificationObserversTask) {
|
||||
RunNotificationObserversTask();
|
||||
}
|
||||
}
|
@ -1,215 +0,0 @@
|
||||
/* -*- 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 nsPerformance_h___
|
||||
#define nsPerformance_h___
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
|
||||
class nsITimedChannel;
|
||||
class nsPerformance;
|
||||
class nsIHttpChannel;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class PerformanceEntry;
|
||||
class PerformanceNavigation;
|
||||
class PerformanceObserver;
|
||||
class PerformanceTiming;
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
// Base class for main-thread and worker Performance API
|
||||
class PerformanceBase : public mozilla::DOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PerformanceBase,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
PerformanceBase();
|
||||
explicit PerformanceBase(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
typedef mozilla::dom::PerformanceEntry PerformanceEntry;
|
||||
typedef mozilla::dom::PerformanceObserver PerformanceObserver;
|
||||
|
||||
void GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval);
|
||||
void GetEntriesByType(const nsAString& aEntryType,
|
||||
nsTArray<RefPtr<PerformanceEntry>>& aRetval);
|
||||
void GetEntriesByName(const nsAString& aName,
|
||||
const mozilla::dom::Optional<nsAString>& aEntryType,
|
||||
nsTArray<RefPtr<PerformanceEntry>>& aRetval);
|
||||
void ClearResourceTimings();
|
||||
|
||||
virtual DOMHighResTimeStamp Now() const = 0;
|
||||
|
||||
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);
|
||||
|
||||
void SetResourceTimingBufferSize(uint64_t aMaxSize);
|
||||
|
||||
void AddObserver(PerformanceObserver* aObserver);
|
||||
void RemoveObserver(PerformanceObserver* aObserver);
|
||||
void NotifyObservers();
|
||||
void CancelNotificationObservers();
|
||||
|
||||
protected:
|
||||
virtual ~PerformanceBase();
|
||||
|
||||
virtual void InsertUserEntry(PerformanceEntry* aEntry);
|
||||
void InsertResourceEntry(PerformanceEntry* aEntry);
|
||||
|
||||
void ClearUserEntries(const mozilla::dom::Optional<nsAString>& aEntryName,
|
||||
const nsAString& aEntryType);
|
||||
|
||||
DOMHighResTimeStamp ResolveTimestampFromName(const nsAString& aName,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
virtual nsISupports* GetAsISupports() = 0;
|
||||
|
||||
virtual void DispatchBufferFullEvent() = 0;
|
||||
|
||||
virtual mozilla::TimeStamp CreationTimeStamp() const = 0;
|
||||
|
||||
virtual DOMHighResTimeStamp CreationTime() const = 0;
|
||||
|
||||
virtual bool IsPerformanceTimingAttribute(const nsAString& aName) = 0;
|
||||
|
||||
virtual DOMHighResTimeStamp
|
||||
GetPerformanceTimingFromString(const nsAString& aTimingName) = 0;
|
||||
|
||||
bool IsResourceEntryLimitReached() const
|
||||
{
|
||||
return mResourceEntries.Length() >= mResourceTimingBufferSize;
|
||||
}
|
||||
|
||||
void LogEntry(PerformanceEntry* aEntry, const nsACString& aOwner) const;
|
||||
void TimingNotification(PerformanceEntry* aEntry, const nsACString& aOwner, uint64_t epoch);
|
||||
|
||||
void RunNotificationObserversTask();
|
||||
void QueueEntry(PerformanceEntry* aEntry);
|
||||
|
||||
DOMHighResTimeStamp RoundTime(double aTime) const;
|
||||
|
||||
nsTObserverArray<PerformanceObserver*> mObservers;
|
||||
|
||||
private:
|
||||
nsTArray<RefPtr<PerformanceEntry>> mUserEntries;
|
||||
nsTArray<RefPtr<PerformanceEntry>> mResourceEntries;
|
||||
|
||||
uint64_t mResourceTimingBufferSize;
|
||||
static const uint64_t kDefaultResourceTimingBufferSize = 150;
|
||||
bool mPendingNotificationObserversTask;
|
||||
};
|
||||
|
||||
// Script "performance" object
|
||||
class nsPerformance final : public PerformanceBase
|
||||
{
|
||||
public:
|
||||
nsPerformance(nsPIDOMWindowInner* aWindow,
|
||||
nsDOMNavigationTiming* aDOMTiming,
|
||||
nsITimedChannel* aChannel,
|
||||
nsPerformance* aParentPerformance);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsPerformance,
|
||||
PerformanceBase)
|
||||
|
||||
static bool IsEnabled(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
static bool IsObserverEnabled(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
nsDOMNavigationTiming* GetDOMTiming() const
|
||||
{
|
||||
return mDOMTiming;
|
||||
}
|
||||
|
||||
nsITimedChannel* GetChannel() const
|
||||
{
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
nsPerformance* GetParentPerformance() const
|
||||
{
|
||||
return mParentPerformance;
|
||||
}
|
||||
|
||||
JSObject* WrapObject(JSContext *cx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// Performance WebIDL methods
|
||||
DOMHighResTimeStamp Now() const override;
|
||||
|
||||
mozilla::dom::PerformanceTiming* Timing();
|
||||
mozilla::dom::PerformanceNavigation* Navigation();
|
||||
|
||||
void AddEntry(nsIHttpChannel* channel,
|
||||
nsITimedChannel* timedChannel);
|
||||
|
||||
using PerformanceBase::GetEntries;
|
||||
using PerformanceBase::GetEntriesByType;
|
||||
using PerformanceBase::GetEntriesByName;
|
||||
using PerformanceBase::ClearResourceTimings;
|
||||
|
||||
using PerformanceBase::Mark;
|
||||
using PerformanceBase::ClearMarks;
|
||||
using PerformanceBase::Measure;
|
||||
using PerformanceBase::ClearMeasures;
|
||||
using PerformanceBase::SetResourceTimingBufferSize;
|
||||
|
||||
void GetMozMemory(JSContext *aCx, JS::MutableHandle<JSObject*> aObj);
|
||||
|
||||
IMPL_EVENT_HANDLER(resourcetimingbufferfull)
|
||||
|
||||
mozilla::TimeStamp CreationTimeStamp() const override;
|
||||
|
||||
DOMHighResTimeStamp CreationTime() const override;
|
||||
|
||||
protected:
|
||||
~nsPerformance();
|
||||
|
||||
nsISupports* GetAsISupports() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void InsertUserEntry(PerformanceEntry* aEntry) override;
|
||||
|
||||
bool IsPerformanceTimingAttribute(const nsAString& aName) override;
|
||||
|
||||
DOMHighResTimeStamp
|
||||
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
|
||||
|
||||
void DispatchBufferFullEvent() override;
|
||||
|
||||
RefPtr<nsDOMNavigationTiming> mDOMTiming;
|
||||
nsCOMPtr<nsITimedChannel> mChannel;
|
||||
RefPtr<mozilla::dom::PerformanceTiming> mTiming;
|
||||
RefPtr<mozilla::dom::PerformanceNavigation> mNavigation;
|
||||
RefPtr<nsPerformance> mParentPerformance;
|
||||
JS::Heap<JSObject*> mMozMemory;
|
||||
};
|
||||
|
||||
#endif /* nsPerformance_h___ */
|
@ -32,11 +32,11 @@ partial interface Performance {
|
||||
// http://www.w3.org/TR/performance-timeline/#sec-window.performance-attribute
|
||||
[Exposed=(Window,Worker)]
|
||||
partial interface Performance {
|
||||
[Func="nsPerformance::IsEnabled"]
|
||||
[Func="Performance::IsEnabled"]
|
||||
PerformanceEntryList getEntries();
|
||||
[Func="nsPerformance::IsEnabled"]
|
||||
[Func="Performance::IsEnabled"]
|
||||
PerformanceEntryList getEntriesByType(DOMString entryType);
|
||||
[Func="nsPerformance::IsEnabled"]
|
||||
[Func="Performance::IsEnabled"]
|
||||
PerformanceEntryList getEntriesByName(DOMString name, optional DOMString
|
||||
entryType);
|
||||
};
|
||||
@ -44,11 +44,11 @@ partial interface Performance {
|
||||
// http://www.w3.org/TR/resource-timing/#extensions-performance-interface
|
||||
[Exposed=Window]
|
||||
partial interface Performance {
|
||||
[Func="nsPerformance::IsEnabled"]
|
||||
[Func="Performance::IsEnabled"]
|
||||
void clearResourceTimings();
|
||||
[Func="nsPerformance::IsEnabled"]
|
||||
[Func="Performance::IsEnabled"]
|
||||
void setResourceTimingBufferSize(unsigned long maxSize);
|
||||
[Func="nsPerformance::IsEnabled"]
|
||||
[Func="Performance::IsEnabled"]
|
||||
attribute EventHandler onresourcetimingbufferfull;
|
||||
};
|
||||
|
||||
@ -62,13 +62,13 @@ partial interface Performance {
|
||||
// http://www.w3.org/TR/user-timing/
|
||||
[Exposed=(Window,Worker)]
|
||||
partial interface Performance {
|
||||
[Func="nsPerformance::IsEnabled", Throws]
|
||||
[Func="Performance::IsEnabled", Throws]
|
||||
void mark(DOMString markName);
|
||||
[Func="nsPerformance::IsEnabled"]
|
||||
[Func="Performance::IsEnabled"]
|
||||
void clearMarks(optional DOMString markName);
|
||||
[Func="nsPerformance::IsEnabled", Throws]
|
||||
[Func="Performance::IsEnabled", Throws]
|
||||
void measure(DOMString measureName, optional DOMString startMark, optional DOMString endMark);
|
||||
[Func="nsPerformance::IsEnabled"]
|
||||
[Func="Performance::IsEnabled"]
|
||||
void clearMeasures(optional DOMString measureName);
|
||||
};
|
||||
|
||||
|
@ -13,7 +13,7 @@ dictionary PerformanceObserverInit {
|
||||
|
||||
callback PerformanceObserverCallback = void (PerformanceObserverEntryList entries, PerformanceObserver observer);
|
||||
|
||||
[Func="nsPerformance::IsObserverEnabled",
|
||||
[Func="Performance::IsObserverEnabled",
|
||||
Constructor(PerformanceObserverCallback callback),
|
||||
Exposed=(Window,Worker)]
|
||||
interface PerformanceObserver {
|
||||
|
@ -14,7 +14,7 @@ dictionary PerformanceEntryFilterOptions {
|
||||
DOMString initiatorType;
|
||||
};
|
||||
|
||||
[Func="nsPerformance::IsObserverEnabled", Exposed=(Window,Worker)]
|
||||
[Func="Performance::IsObserverEnabled", Exposed=(Window,Worker)]
|
||||
interface PerformanceObserverEntryList {
|
||||
PerformanceEntryList getEntries(optional PerformanceEntryFilterOptions filter);
|
||||
PerformanceEntryList getEntriesByType(DOMString entryType);
|
||||
|
@ -1,65 +0,0 @@
|
||||
/* -*- 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_workers_performance_h__
|
||||
#define mozilla_dom_workers_performance_h__
|
||||
|
||||
#include "nsWrapperCache.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "Workers.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsPerformance.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class WorkerPrivate;
|
||||
|
||||
class Performance final : public PerformanceBase
|
||||
{
|
||||
public:
|
||||
explicit Performance(WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
private:
|
||||
~Performance();
|
||||
|
||||
void InsertUserEntry(PerformanceEntry* aEntry) override;
|
||||
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
|
||||
public:
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// WebIDL (public APIs)
|
||||
DOMHighResTimeStamp Now() const override;
|
||||
|
||||
using PerformanceBase::Mark;
|
||||
using PerformanceBase::ClearMarks;
|
||||
using PerformanceBase::Measure;
|
||||
using PerformanceBase::ClearMeasures;
|
||||
|
||||
private:
|
||||
nsISupports* GetAsISupports() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DispatchBufferFullEvent() override;
|
||||
|
||||
bool IsPerformanceTimingAttribute(const nsAString& aName) override;
|
||||
|
||||
DOMHighResTimeStamp
|
||||
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
|
||||
|
||||
TimeStamp CreationTimeStamp() const override;
|
||||
|
||||
DOMHighResTimeStamp CreationTime() const override;
|
||||
};
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_workers_performance_h__
|
@ -30,7 +30,6 @@
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
#include "nsIWorkerDebugger.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -56,6 +55,7 @@
|
||||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/MessagePortBinding.h"
|
||||
#include "mozilla/dom/MessagePortList.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/PMessagePort.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseDebugging.h"
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "mozilla/dom/IDBFactory.h"
|
||||
#include "mozilla/dom/ImageBitmap.h"
|
||||
#include "mozilla/dom/ImageBitmapBinding.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseWorkerProxy.h"
|
||||
#include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h"
|
||||
@ -42,7 +43,6 @@
|
||||
#include "ScriptLoader.h"
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
#include "Performance.h"
|
||||
#include "ServiceWorkerClients.h"
|
||||
#include "ServiceWorkerManager.h"
|
||||
#include "ServiceWorkerRegistration.h"
|
||||
@ -359,7 +359,7 @@ WorkerGlobalScope::GetPerformance()
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
if (!mPerformance) {
|
||||
mPerformance = new Performance(mWorkerPrivate);
|
||||
mPerformance = Performance::CreateForWorker(mWorkerPrivate);
|
||||
}
|
||||
|
||||
return mPerformance;
|
||||
|
@ -24,6 +24,7 @@ class Crypto;
|
||||
class Function;
|
||||
class IDBFactory;
|
||||
enum class ImageBitmapFormat : uint32_t;
|
||||
class Performance;
|
||||
class Promise;
|
||||
class RequestOrUSVString;
|
||||
class ServiceWorkerRegistrationWorkerThread;
|
||||
@ -42,7 +43,6 @@ BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class ServiceWorkerClients;
|
||||
class WorkerPrivate;
|
||||
class Performance;
|
||||
|
||||
class WorkerGlobalScope : public DOMEventTargetHelper,
|
||||
public nsIGlobalObject,
|
||||
|
@ -32,7 +32,6 @@ EXPORTS.mozilla.dom.workers += [
|
||||
|
||||
# Stuff needed for the bindings, not really public though.
|
||||
EXPORTS.mozilla.dom.workers.bindings += [
|
||||
'Performance.h',
|
||||
'ServiceWorker.h',
|
||||
'ServiceWorkerClient.h',
|
||||
'ServiceWorkerClients.h',
|
||||
@ -54,7 +53,6 @@ XPIDL_SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'ChromeWorkerScope.cpp',
|
||||
'FileReaderSync.cpp',
|
||||
'Performance.cpp',
|
||||
'Principal.cpp',
|
||||
'RegisterBindings.cpp',
|
||||
'RuntimeService.cpp',
|
||||
|
@ -128,7 +128,7 @@
|
||||
#include "nsArenaMemoryStats.h"
|
||||
#include "nsFrameSelection.h"
|
||||
|
||||
#include "nsPerformance.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
|
||||
@ -9417,7 +9417,7 @@ PresShell::GetPerformanceNow()
|
||||
DOMHighResTimeStamp now = 0;
|
||||
|
||||
if (nsPIDOMWindowInner* window = mDocument->GetInnerWindow()) {
|
||||
nsPerformance* perf = window->GetPerformance();
|
||||
Performance* perf = window->GetPerformance();
|
||||
|
||||
if (perf) {
|
||||
now = perf->Now();
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "nsViewManager.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/WindowBinding.h"
|
||||
#include "mozilla/RestyleManager.h"
|
||||
#include "mozilla/RestyleManagerHandle.h"
|
||||
@ -1605,7 +1605,7 @@ nsRefreshDriver::RunFrameRequestCallbacks(TimeStamp aNowTime)
|
||||
docCallbacks.mDocument->GetInnerWindow();
|
||||
DOMHighResTimeStamp timeStamp = 0;
|
||||
if (innerWindow && innerWindow->IsInnerWindow()) {
|
||||
nsPerformance* perf = innerWindow->GetPerformance();
|
||||
mozilla::dom::Performance* perf = innerWindow->GetPerformance();
|
||||
if (perf) {
|
||||
timeStamp = perf->GetDOMTiming()->TimeStampToDOMHighRes(aNowTime);
|
||||
}
|
||||
|
@ -55,9 +55,9 @@
|
||||
#endif // XP_WIN
|
||||
|
||||
#include "nsIDocument.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsDOMDataChannel.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
@ -2093,7 +2093,7 @@ PeerConnectionImpl::SetRemoteDescription(int32_t action, const char* aSDP)
|
||||
nsresult
|
||||
PeerConnectionImpl::GetTimeSinceEpoch(DOMHighResTimeStamp *result) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsPerformance *perf = mWindow->GetPerformance();
|
||||
Performance *perf = mWindow->GetPerformance();
|
||||
NS_ENSURE_TRUE(perf && perf->Timing(), NS_ERROR_UNEXPECTED);
|
||||
*result = perf->Now() + perf->Timing()->NavigationStart();
|
||||
return NS_OK;
|
||||
|
@ -38,8 +38,8 @@
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsINetworkInterceptController.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozIThirdPartyUtil.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsContentSecurityManager.h"
|
||||
@ -3340,10 +3340,10 @@ IMPL_TIMING_ATTR(RedirectEnd)
|
||||
|
||||
#undef IMPL_TIMING_ATTR
|
||||
|
||||
nsPerformance*
|
||||
mozilla::dom::Performance*
|
||||
HttpBaseChannel::GetPerformance()
|
||||
{
|
||||
// If performance timing is disabled, there is no need for the nsPerformance
|
||||
// If performance timing is disabled, there is no need for the Performance
|
||||
// object anymore.
|
||||
if (!mTimingEnabled) {
|
||||
return nullptr;
|
||||
@ -3380,7 +3380,7 @@ HttpBaseChannel::GetPerformance()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsPerformance* docPerformance = innerWindow->GetPerformance();
|
||||
mozilla::dom::Performance* docPerformance = innerWindow->GetPerformance();
|
||||
if (!docPerformance) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -44,12 +44,15 @@
|
||||
#include "nsCOMArray.h"
|
||||
#include "mozilla/net/ChannelEventQueue.h"
|
||||
|
||||
class nsPerformance;
|
||||
class nsISecurityConsoleMessage;
|
||||
class nsIPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class Performance;
|
||||
}
|
||||
|
||||
class LogCollector;
|
||||
|
||||
namespace net {
|
||||
@ -321,7 +324,7 @@ protected:
|
||||
// drop reference to listener, its callbacks, and the progress sink
|
||||
void ReleaseListeners();
|
||||
|
||||
nsPerformance* GetPerformance();
|
||||
mozilla::dom::Performance* GetPerformance();
|
||||
nsIURI* GetReferringPage();
|
||||
nsPIDOMWindowInner* GetInnerDOMWindow();
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/ipc/InputStreamUtils.h"
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
@ -32,7 +33,6 @@
|
||||
#include "SerializedLoadContext.h"
|
||||
#include "nsInputStreamPump.h"
|
||||
#include "InterceptedChannel.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "mozIThirdPartyUtil.h"
|
||||
#include "nsContentSecurityManager.h"
|
||||
#include "nsIDeprecationWarner.h"
|
||||
@ -889,7 +889,7 @@ HttpChannelChild::OnStopRequest(const nsresult& channelStatus,
|
||||
mCacheReadStart = timing.cacheReadStart;
|
||||
mCacheReadEnd = timing.cacheReadEnd;
|
||||
|
||||
nsPerformance* documentPerformance = GetPerformance();
|
||||
Performance* documentPerformance = GetPerformance();
|
||||
if (documentPerformance) {
|
||||
documentPerformance->AddEntry(this, this);
|
||||
}
|
||||
|
@ -79,8 +79,8 @@
|
||||
#include "nsISiteSecurityService.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "CacheObserver.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "AlternateServices.h"
|
||||
#include "InterceptedChannel.h"
|
||||
@ -6393,7 +6393,7 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st
|
||||
}
|
||||
|
||||
// Register entry to the Performance resource timing
|
||||
nsPerformance* documentPerformance = GetPerformance();
|
||||
mozilla::dom::Performance* documentPerformance = GetPerformance();
|
||||
if (documentPerformance) {
|
||||
documentPerformance->AddEntry(this, this);
|
||||
}
|
||||
|
@ -538,7 +538,7 @@ nsHttpTransaction::OnTransportStatus(nsITransport* transport,
|
||||
// then the requestStart timestamp will be null, so we mark the timestamps
|
||||
// for domainLookupStart/End and connectStart/End
|
||||
// If we are using a persistent connection they will remain null,
|
||||
// and the correct value will be returned in nsPerformance.
|
||||
// and the correct value will be returned in Performance.
|
||||
if (TimingEnabled() && GetRequestStart().IsNull()) {
|
||||
if (status == NS_NET_STATUS_RESOLVING_HOST) {
|
||||
SetDomainLookupStart(TimeStamp::Now(), true);
|
||||
|
Loading…
Reference in New Issue
Block a user