summaryrefslogtreecommitdiffstats
path: root/dom/performance/PerformanceResourceTiming.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/performance/PerformanceResourceTiming.cpp')
-rw-r--r--dom/performance/PerformanceResourceTiming.cpp134
1 files changed, 134 insertions, 0 deletions
diff --git a/dom/performance/PerformanceResourceTiming.cpp b/dom/performance/PerformanceResourceTiming.cpp
new file mode 100644
index 0000000000..40a0b77382
--- /dev/null
+++ b/dom/performance/PerformanceResourceTiming.cpp
@@ -0,0 +1,134 @@
+/* -*- 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 "PerformanceResourceTiming.h"
+#include "mozilla/dom/PerformanceResourceTimingBinding.h"
+#include "nsNetUtil.h"
+#include "nsArrayUtils.h"
+
+using namespace mozilla::dom;
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformanceResourceTiming, PerformanceEntry,
+ mPerformance)
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceResourceTiming,
+ PerformanceEntry)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceResourceTiming)
+NS_INTERFACE_MAP_END_INHERITING(PerformanceEntry)
+
+NS_IMPL_ADDREF_INHERITED(PerformanceResourceTiming, PerformanceEntry)
+NS_IMPL_RELEASE_INHERITED(PerformanceResourceTiming, PerformanceEntry)
+
+PerformanceResourceTiming::PerformanceResourceTiming(
+ UniquePtr<PerformanceTimingData>&& aPerformanceTiming,
+ Performance* aPerformance, const nsAString& aName)
+ : PerformanceEntry(aPerformance->GetParentObject(), aName, u"resource"_ns),
+ mTimingData(std::move(aPerformanceTiming)),
+ mPerformance(aPerformance) {
+ MOZ_RELEASE_ASSERT(mTimingData);
+ MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
+ if (NS_IsMainThread()) {
+ // Used to check if an addon content script has access to this timing.
+ // We don't need it in workers, and ignore mOriginalURI if null.
+ NS_NewURI(getter_AddRefs(mOriginalURI), aName);
+ }
+}
+
+PerformanceResourceTiming::~PerformanceResourceTiming() = default;
+
+DOMHighResTimeStamp PerformanceResourceTiming::FetchStart() const {
+ if (mTimingData->TimingAllowed()) {
+ return mTimingData->FetchStartHighRes(mPerformance);
+ }
+ return StartTime();
+}
+
+DOMHighResTimeStamp PerformanceResourceTiming::StartTime() const {
+ // Force the start time to be the earliest of:
+ // - RedirectStart
+ // - WorkerStart
+ // - AsyncOpen
+ // Ignore zero values. The RedirectStart and WorkerStart values
+ // can come from earlier redirected channels prior to the AsyncOpen
+ // time being recorded.
+ if (mCachedStartTime.isNothing()) {
+ DOMHighResTimeStamp redirect =
+ mTimingData->RedirectStartHighRes(mPerformance);
+ redirect = redirect ? redirect : DBL_MAX;
+
+ DOMHighResTimeStamp worker = mTimingData->WorkerStartHighRes(mPerformance);
+ worker = worker ? worker : DBL_MAX;
+
+ DOMHighResTimeStamp asyncOpen = mTimingData->AsyncOpenHighRes(mPerformance);
+
+ mCachedStartTime.emplace(std::min(asyncOpen, std::min(redirect, worker)));
+ }
+ return mCachedStartTime.value();
+}
+
+JSObject* PerformanceResourceTiming::WrapObject(
+ JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
+ return PerformanceResourceTiming_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+size_t PerformanceResourceTiming::SizeOfIncludingThis(
+ mozilla::MallocSizeOf aMallocSizeOf) const {
+ return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
+}
+
+size_t PerformanceResourceTiming::SizeOfExcludingThis(
+ mozilla::MallocSizeOf aMallocSizeOf) const {
+ return PerformanceEntry::SizeOfExcludingThis(aMallocSizeOf) +
+ mInitiatorType.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
+ mTimingData->NextHopProtocol().SizeOfExcludingThisIfUnshared(
+ aMallocSizeOf);
+}
+
+void PerformanceResourceTiming::GetServerTiming(
+ nsTArray<RefPtr<PerformanceServerTiming>>& aRetval,
+ Maybe<nsIPrincipal*>& aSubjectPrincipal) {
+ aRetval.Clear();
+ if (!TimingAllowedForCaller(aSubjectPrincipal)) {
+ return;
+ }
+
+ nsTArray<nsCOMPtr<nsIServerTiming>> serverTimingArray =
+ mTimingData->GetServerTiming();
+ uint32_t length = serverTimingArray.Length();
+ for (uint32_t index = 0; index < length; ++index) {
+ nsCOMPtr<nsIServerTiming> serverTiming = serverTimingArray.ElementAt(index);
+ MOZ_ASSERT(serverTiming);
+
+ aRetval.AppendElement(
+ new PerformanceServerTiming(GetParentObject(), serverTiming));
+ }
+}
+
+bool PerformanceResourceTiming::TimingAllowedForCaller(
+ Maybe<nsIPrincipal*>& aCaller) const {
+ if (mTimingData->TimingAllowed()) {
+ return true;
+ }
+
+ // Check if the addon has permission to access the cross-origin resource.
+ return mOriginalURI && aCaller.isSome() &&
+ BasePrincipal::Cast(aCaller.value())->AddonAllowsLoad(mOriginalURI);
+}
+
+bool PerformanceResourceTiming::ReportRedirectForCaller(
+ Maybe<nsIPrincipal*>& aCaller, bool aEnsureSameOriginAndIgnoreTAO) const {
+ if (mTimingData->ShouldReportCrossOriginRedirect(
+ aEnsureSameOriginAndIgnoreTAO)) {
+ return true;
+ }
+
+ // Only report cross-origin redirect if the addon has <all_urls> permission.
+ return aCaller.isSome() &&
+ BasePrincipal::Cast(aCaller.value())
+ ->AddonHasPermission(nsGkAtoms::all_urlsPermission);
+}