Files
palemoon27/dom/base/nsPerformance.h
T
roytam1 9e4ed9857d import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1183825 - Hide PushMessageData methods until we support sending push data. r=mt,smaug (c07f6b6c9)
- Bug 1186880 - Performance timing api in workers should output entries if preference is enabled. r=baku (642bd335a)
- Bug 1188091 - Fix the exposure of Push interfaces; r=dougt,bzbarsky,nsm Currently we don't check the dom.push.enabled pref in some cases for some of these interfaces.  This patch unifies how all of these interfaces are exposed to Window, Worker, and ServiceWorker. (dbe4ebfcc)
- Bug 1188062 - Unship Request.context; r=baku (6ca2ebcf6)
- Bug 1162714 - Don't let YCM generate machc. r=ehsan (7c5f36c12)
- Bug 1160897 - Fixing .ycm_extra_conf for Fennec. r=ehsan (22adf0705)
- goanna->gecko (94b69bd6c)
- improve (e87b53162)
- Bug 1147939 - The expression decompiler can't assume that it's called directly from script. (r=bhackett) (4759a5210)
- Bug 1188609 - Remove mirroring support from RokuApp (Toolkit) r=snorp (81a0bb66a)
- Bug 1050749 - Expose BatteryManager via getBattery() returning a Promise. r=bz, r=baku, r=jgraham (67d2dd502)
- Bug 1182347 - Remove nsIPrincipal::cookieJar. r=sicking (855d0e8ce)
- remove double method, probably misspach (3c256c5b4)
- Bug 1182357 - Add an API to mint nsExpandedPrincipals. r=mrbkap (42de17cfd)
- Bug 1172080 - Part 1: Throw when requesting origin for poorly behaved URIs, r=bholley (c8410f3c6)
- Bug 1124126 - Retry database connection for the case of corrupted permissions.sqlite. r=bsmedberg (748e9205a)
2021-12-23 09:44:29 +08:00

468 lines
15 KiB
C++

/* -*- 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;
} // namespace dom
} // namespace mozilla
// Script "performance.timing" object
class nsPerformanceTiming final : public nsWrapperCache
{
public:
typedef mozilla::TimeStamp TimeStamp;
/**
* @param aPerformance
* The performance object (the JS parent).
* This will allow access to "window.performance.timing" attribute for
* the navigation timing (can't be null).
* @param aChannel
* An nsITimedChannel used to gather all the networking timings by both
* the navigation timing and the resource timing (can't be null).
* @param aHttpChannel
* An nsIHttpChannel (the resource's http channel).
* This will be used by the resource timing cross-domain check
* algorithm.
* Argument is null for the navigation timing (navigation timing uses
* another algorithm for the cross-domain redirects).
* @param aZeroTime
* The offset that will be added to the timestamp of each event. This
* argument should be equal to performance.navigationStart for
* navigation timing and "0" for the resource timing.
*/
nsPerformanceTiming(nsPerformance* aPerformance,
nsITimedChannel* aChannel,
nsIHttpChannel* aHttpChannel,
DOMHighResTimeStamp aZeroTime);
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsPerformanceTiming)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsPerformanceTiming)
nsDOMNavigationTiming* GetDOMTiming() const;
nsPerformance* GetParentObject() const
{
return mPerformance;
}
/**
* @param aStamp
* The TimeStamp recorded for a specific event. This TimeStamp can
* be null.
* @return the duration of an event with a given TimeStamp, relative to the
* navigationStart TimeStamp (the moment the user landed on the
* page), if the given TimeStamp is valid. Otherwise, it will return
* the FetchStart timing value.
*/
inline DOMHighResTimeStamp TimeStampToDOMHighResOrFetchStart(TimeStamp aStamp)
{
return (!aStamp.IsNull())
? TimeStampToDOMHighRes(aStamp)
: FetchStartHighRes();
}
/**
* The nsITimedChannel records an absolute timestamp for each event.
* The nsDOMNavigationTiming will record the moment when the user landed on
* the page. This is a window.performance unique timestamp, so it can be used
* for all the events (navigation timing and resource timing events).
*
* The algorithm operates in 2 steps:
* 1. The first step is to subtract the two timestamps: the argument (the
* envet's timesramp) and the navigation start timestamp. This will result in
* a relative timestamp of the event (relative to the navigation start -
* window.performance.timing.navigationStart).
* 2. The second step is to add any required offset (the mZeroTime). For now,
* this offset value is either 0 (for the resource timing), or equal to
* "performance.navigationStart" (for navigation timing).
* For the resource timing, mZeroTime is set to 0, causing the result to be a
* relative time.
* For the navigation timing, mZeroTime is set to "performance.navigationStart"
* causing the result be an absolute time.
*
* @param aStamp
* The TimeStamp recorded for a specific event. This TimeStamp can't
* be null.
* @return number of milliseconds value as one of:
* - relative to the navigation start time, time the user has landed on the
* page
* - an absolute wall clock time since the unix epoch
*/
inline DOMHighResTimeStamp TimeStampToDOMHighRes(TimeStamp aStamp) const
{
MOZ_ASSERT(!aStamp.IsNull());
mozilla::TimeDuration duration =
aStamp - GetDOMTiming()->GetNavigationStartTimeStamp();
return duration.ToMilliseconds() + mZeroTime;
}
virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
// PerformanceNavigation WebIDL methods
DOMTimeMilliSec NavigationStart() const {
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
return GetDOMTiming()->GetNavigationStart();
}
DOMTimeMilliSec UnloadEventStart() {
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
return GetDOMTiming()->GetUnloadEventStart();
}
DOMTimeMilliSec UnloadEventEnd() {
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
return GetDOMTiming()->GetUnloadEventEnd();
}
uint16_t GetRedirectCount() const;
// Checks if the resource is either same origin as the page that started
// the load, or if the response contains the Timing-Allow-Origin header
// with a value of * or matching the domain of the loading Principal
bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, nsITimedChannel* aChannel);
// Cached result of CheckAllowedOrigin. If false, security sensitive
// attributes of the resourceTiming object will be set to 0
bool TimingAllowed() const;
// If this is false the values of redirectStart/End will be 0
// This is false if no redirects occured, or if any of the responses failed
// the timing-allow-origin check in HttpBaseChannel::TimingAllowCheck
bool ShouldReportCrossOriginRedirect() const;
// High resolution (used by resource timing)
DOMHighResTimeStamp FetchStartHighRes();
DOMHighResTimeStamp RedirectStartHighRes();
DOMHighResTimeStamp RedirectEndHighRes();
DOMHighResTimeStamp DomainLookupStartHighRes();
DOMHighResTimeStamp DomainLookupEndHighRes();
DOMHighResTimeStamp ConnectStartHighRes();
DOMHighResTimeStamp ConnectEndHighRes();
DOMHighResTimeStamp RequestStartHighRes();
DOMHighResTimeStamp ResponseStartHighRes();
DOMHighResTimeStamp ResponseEndHighRes();
// Low resolution (used by navigation timing)
DOMTimeMilliSec FetchStart();
DOMTimeMilliSec RedirectStart();
DOMTimeMilliSec RedirectEnd();
DOMTimeMilliSec DomainLookupStart();
DOMTimeMilliSec DomainLookupEnd();
DOMTimeMilliSec ConnectStart();
DOMTimeMilliSec ConnectEnd();
DOMTimeMilliSec RequestStart();
DOMTimeMilliSec ResponseStart();
DOMTimeMilliSec ResponseEnd();
DOMTimeMilliSec DomLoading() {
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
return GetDOMTiming()->GetDomLoading();
}
DOMTimeMilliSec DomInteractive() const {
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
return GetDOMTiming()->GetDomInteractive();
}
DOMTimeMilliSec DomContentLoadedEventStart() const {
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
return GetDOMTiming()->GetDomContentLoadedEventStart();
}
DOMTimeMilliSec DomContentLoadedEventEnd() const {
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
return GetDOMTiming()->GetDomContentLoadedEventEnd();
}
DOMTimeMilliSec DomComplete() const {
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
return GetDOMTiming()->GetDomComplete();
}
DOMTimeMilliSec LoadEventStart() const {
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
return GetDOMTiming()->GetLoadEventStart();
}
DOMTimeMilliSec LoadEventEnd() const {
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
return GetDOMTiming()->GetLoadEventEnd();
}
private:
~nsPerformanceTiming();
bool IsInitialized() const;
void InitializeTimingInfo(nsITimedChannel* aChannel);
nsRefPtr<nsPerformance> mPerformance;
DOMHighResTimeStamp mFetchStart;
// This is an offset that will be added to each timing ([ms] resolution).
// There are only 2 possible values: (1) logicaly equal to navigationStart
// TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results
// are relative to the navigation start).
DOMHighResTimeStamp mZeroTime;
TimeStamp mAsyncOpen;
TimeStamp mRedirectStart;
TimeStamp mRedirectEnd;
TimeStamp mDomainLookupStart;
TimeStamp mDomainLookupEnd;
TimeStamp mConnectStart;
TimeStamp mConnectEnd;
TimeStamp mRequestStart;
TimeStamp mResponseStart;
TimeStamp mCacheReadStart;
TimeStamp mResponseEnd;
TimeStamp mCacheReadEnd;
uint16_t mRedirectCount;
bool mTimingAllowed;
bool mAllRedirectsSameOrigin;
bool mInitialized;
// If the resourceTiming object should have non-zero redirectStart and
// redirectEnd attributes. It is false if there were no redirects, or if
// any of the responses didn't pass the timing-allow-check
bool mReportCrossOriginRedirect;
};
// Script "performance.navigation" object
class nsPerformanceNavigation final : public nsWrapperCache
{
public:
explicit nsPerformanceNavigation(nsPerformance* aPerformance);
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsPerformanceNavigation)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsPerformanceNavigation)
nsDOMNavigationTiming* GetDOMTiming() const;
nsPerformanceTiming* GetPerformanceTiming() const;
nsPerformance* GetParentObject() const
{
return mPerformance;
}
virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
// PerformanceNavigation WebIDL methods
uint16_t Type() const {
return GetDOMTiming()->GetType();
}
uint16_t RedirectCount() const {
return GetPerformanceTiming()->GetRedirectCount();
}
private:
~nsPerformanceNavigation();
nsRefPtr<nsPerformance> mPerformance;
};
// 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(nsPIDOMWindow* aWindow);
typedef mozilla::dom::PerformanceEntry PerformanceEntry;
void GetEntries(nsTArray<nsRefPtr<PerformanceEntry>>& aRetval);
void GetEntriesByType(const nsAString& aEntryType,
nsTArray<nsRefPtr<PerformanceEntry>>& aRetval);
void GetEntriesByName(const nsAString& aName,
const mozilla::dom::Optional<nsAString>& aEntryType,
nsTArray<nsRefPtr<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);
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 DOMHighResTimeStamp
DeltaFromNavigationStart(DOMHighResTimeStamp aTime) = 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;
private:
nsTArray<nsRefPtr<PerformanceEntry>> mUserEntries;
nsTArray<nsRefPtr<PerformanceEntry>> mResourceEntries;
uint64_t mResourceTimingBufferSize;
static const uint64_t kDefaultResourceTimingBufferSize = 150;
};
// Script "performance" object
class nsPerformance final : public PerformanceBase
{
public:
nsPerformance(nsPIDOMWindow* 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);
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;
nsPerformanceTiming* Timing();
nsPerformanceNavigation* 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)
private:
~nsPerformance();
nsISupports* GetAsISupports() override
{
return this;
}
void InsertUserEntry(PerformanceEntry* aEntry);
bool IsPerformanceTimingAttribute(const nsAString& aName) override;
DOMHighResTimeStamp
DeltaFromNavigationStart(DOMHighResTimeStamp aTime) override;
DOMHighResTimeStamp
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
void DispatchBufferFullEvent() override;
nsRefPtr<nsDOMNavigationTiming> mDOMTiming;
nsCOMPtr<nsITimedChannel> mChannel;
nsRefPtr<nsPerformanceTiming> mTiming;
nsRefPtr<nsPerformanceNavigation> mNavigation;
nsRefPtr<nsPerformance> mParentPerformance;
JS::Heap<JSObject*> mMozMemory;
};
inline nsDOMNavigationTiming*
nsPerformanceNavigation::GetDOMTiming() const
{
return mPerformance->GetDOMTiming();
}
inline nsPerformanceTiming*
nsPerformanceNavigation::GetPerformanceTiming() const
{
return mPerformance->Timing();
}
inline nsDOMNavigationTiming*
nsPerformanceTiming::GetDOMTiming() const
{
return mPerformance->GetDOMTiming();
}
#endif /* nsPerformance_h___ */