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::StartTime() const {
45 // Force the start time to be the earliest of:
49 // Ignore zero values. The RedirectStart and WorkerStart values
50 // can come from earlier redirected channels prior to the AsyncOpen
51 // time being recorded.
52 if (mCachedStartTime
.isNothing()) {
53 DOMHighResTimeStamp redirect
=
54 mTimingData
->RedirectStartHighRes(mPerformance
);
55 redirect
= redirect
? redirect
: DBL_MAX
;
57 DOMHighResTimeStamp worker
= mTimingData
->WorkerStartHighRes(mPerformance
);
58 worker
= worker
? worker
: DBL_MAX
;
60 DOMHighResTimeStamp asyncOpen
= mTimingData
->AsyncOpenHighRes(mPerformance
);
62 mCachedStartTime
.emplace(std::min(asyncOpen
, std::min(redirect
, worker
)));
64 return mCachedStartTime
.value();
67 JSObject
* PerformanceResourceTiming::WrapObject(
68 JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
) {
69 return PerformanceResourceTiming_Binding::Wrap(aCx
, this, aGivenProto
);
72 size_t PerformanceResourceTiming::SizeOfIncludingThis(
73 mozilla::MallocSizeOf aMallocSizeOf
) const {
74 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf
);
77 size_t PerformanceResourceTiming::SizeOfExcludingThis(
78 mozilla::MallocSizeOf aMallocSizeOf
) const {
79 return PerformanceEntry::SizeOfExcludingThis(aMallocSizeOf
) +
80 mInitiatorType
.SizeOfExcludingThisIfUnshared(aMallocSizeOf
) +
81 mTimingData
->NextHopProtocol().SizeOfExcludingThisIfUnshared(
85 void PerformanceResourceTiming::GetServerTiming(
86 nsTArray
<RefPtr
<PerformanceServerTiming
>>& aRetval
,
87 Maybe
<nsIPrincipal
*>& aSubjectPrincipal
) {
89 if (!TimingAllowedForCaller(aSubjectPrincipal
)) {
93 nsTArray
<nsCOMPtr
<nsIServerTiming
>> serverTimingArray
=
94 mTimingData
->GetServerTiming();
95 uint32_t length
= serverTimingArray
.Length();
96 for (uint32_t index
= 0; index
< length
; ++index
) {
97 nsCOMPtr
<nsIServerTiming
> serverTiming
= serverTimingArray
.ElementAt(index
);
98 MOZ_ASSERT(serverTiming
);
100 aRetval
.AppendElement(
101 new PerformanceServerTiming(GetParentObject(), serverTiming
));
105 bool PerformanceResourceTiming::TimingAllowedForCaller(
106 Maybe
<nsIPrincipal
*>& aCaller
) const {
107 if (mTimingData
->TimingAllowed()) {
111 // Check if the addon has permission to access the cross-origin resource.
112 return mOriginalURI
&& aCaller
.isSome() &&
113 BasePrincipal::Cast(aCaller
.value())->AddonAllowsLoad(mOriginalURI
);
116 bool PerformanceResourceTiming::ReportRedirectForCaller(
117 Maybe
<nsIPrincipal
*>& aCaller
, bool aEnsureSameOriginAndIgnoreTAO
) const {
118 if (mTimingData
->ShouldReportCrossOriginRedirect(
119 aEnsureSameOriginAndIgnoreTAO
)) {
123 // Only report cross-origin redirect if the addon has <all_urls> permission.
124 return aCaller
.isSome() &&
125 BasePrincipal::Cast(aCaller
.value())
126 ->AddonHasPermission(nsGkAtoms::all_urlsPermission
);