1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "PerformanceResourceTiming.h"
8 #include "mozilla/dom/PerformanceResourceTimingBinding.h"
10 #include "nsArrayUtils.h"
12 using namespace mozilla::dom
;
14 NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformanceResourceTiming
, PerformanceEntry
,
17 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceResourceTiming
,
19 NS_IMPL_CYCLE_COLLECTION_TRACE_END
21 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceResourceTiming
)
22 NS_INTERFACE_MAP_END_INHERITING(PerformanceEntry
)
24 NS_IMPL_ADDREF_INHERITED(PerformanceResourceTiming
, PerformanceEntry
)
25 NS_IMPL_RELEASE_INHERITED(PerformanceResourceTiming
, PerformanceEntry
)
27 PerformanceResourceTiming::PerformanceResourceTiming(
28 UniquePtr
<PerformanceTimingData
>&& aPerformanceTiming
,
29 Performance
* aPerformance
, const nsAString
& aName
)
30 : PerformanceEntry(aPerformance
->GetParentObject(), aName
, u
"resource"_ns
),
31 mTimingData(std::move(aPerformanceTiming
)),
32 mPerformance(aPerformance
) {
33 MOZ_RELEASE_ASSERT(mTimingData
);
34 MOZ_ASSERT(aPerformance
, "Parent performance object should be provided");
35 if (NS_IsMainThread()) {
36 // Used to check if an addon content script has access to this timing.
37 // We don't need it in workers, and ignore mOriginalURI if null.
38 NS_NewURI(getter_AddRefs(mOriginalURI
), aName
);
42 PerformanceResourceTiming::~PerformanceResourceTiming() = default;
44 DOMHighResTimeStamp
PerformanceResourceTiming::FetchStart() const {
45 if (mTimingData
->TimingAllowed()) {
46 return mTimingData
->FetchStartHighRes(mPerformance
);
51 DOMHighResTimeStamp
PerformanceResourceTiming::StartTime() const {
52 // Force the start time to be the earliest of:
56 // Ignore zero values. The RedirectStart and WorkerStart values
57 // can come from earlier redirected channels prior to the AsyncOpen
58 // time being recorded.
59 if (mCachedStartTime
.isNothing()) {
60 DOMHighResTimeStamp redirect
=
61 mTimingData
->RedirectStartHighRes(mPerformance
);
62 redirect
= redirect
? redirect
: DBL_MAX
;
64 DOMHighResTimeStamp worker
= mTimingData
->WorkerStartHighRes(mPerformance
);
65 worker
= worker
? worker
: DBL_MAX
;
67 DOMHighResTimeStamp asyncOpen
= mTimingData
->AsyncOpenHighRes(mPerformance
);
69 mCachedStartTime
.emplace(std::min(asyncOpen
, std::min(redirect
, worker
)));
71 return mCachedStartTime
.value();
74 JSObject
* PerformanceResourceTiming::WrapObject(
75 JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
) {
76 return PerformanceResourceTiming_Binding::Wrap(aCx
, this, aGivenProto
);
79 size_t PerformanceResourceTiming::SizeOfIncludingThis(
80 mozilla::MallocSizeOf aMallocSizeOf
) const {
81 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf
);
84 size_t PerformanceResourceTiming::SizeOfExcludingThis(
85 mozilla::MallocSizeOf aMallocSizeOf
) const {
86 return PerformanceEntry::SizeOfExcludingThis(aMallocSizeOf
) +
87 mInitiatorType
.SizeOfExcludingThisIfUnshared(aMallocSizeOf
) +
88 mTimingData
->NextHopProtocol().SizeOfExcludingThisIfUnshared(
92 void PerformanceResourceTiming::GetServerTiming(
93 nsTArray
<RefPtr
<PerformanceServerTiming
>>& aRetval
,
94 nsIPrincipal
& aSubjectPrincipal
) {
96 if (!TimingAllowedForCaller(aSubjectPrincipal
)) {
100 nsTArray
<nsCOMPtr
<nsIServerTiming
>> serverTimingArray
=
101 mTimingData
->GetServerTiming();
102 uint32_t length
= serverTimingArray
.Length();
103 for (uint32_t index
= 0; index
< length
; ++index
) {
104 nsCOMPtr
<nsIServerTiming
> serverTiming
= serverTimingArray
.ElementAt(index
);
105 MOZ_ASSERT(serverTiming
);
107 aRetval
.AppendElement(
108 new PerformanceServerTiming(GetParentObject(), serverTiming
));
112 bool PerformanceResourceTiming::TimingAllowedForCaller(
113 nsIPrincipal
& aCaller
) const {
114 if (mTimingData
->TimingAllowed()) {
118 // Check if the addon has permission to access the cross-origin resource.
119 return mOriginalURI
&&
120 BasePrincipal::Cast(&aCaller
)->AddonAllowsLoad(mOriginalURI
);
123 bool PerformanceResourceTiming::ReportRedirectForCaller(
124 nsIPrincipal
& aCaller
, bool aEnsureSameOriginAndIgnoreTAO
) const {
125 if (mTimingData
->ShouldReportCrossOriginRedirect(
126 aEnsureSameOriginAndIgnoreTAO
)) {
130 // Only report cross-origin redirect if the addon has <all_urls> permission.
131 return BasePrincipal::Cast(&aCaller
)->AddonHasPermission(
132 nsGkAtoms::all_urlsPermission
);