From dfd9fce56965acbc9c220aa98fd32f94a92b018a Mon Sep 17 00:00:00 2001 From: Kershaw Chang Date: Wed, 10 Jan 2018 04:01:00 -0500 Subject: [PATCH] Bug 1423495 - Part 1: Implement PerformanceServerTiming. r=baku This patch includes: 1. Introduce PerformanceServerTiming.webidl. 2. Add serverTiming in PerformanceResourceTiming.webidl. 3. Get serverTiming data from nsITimedChannel and keep it in PerformanceTimng class. 4. Add PerformanceServerTiming to test_interfaces.js. --- dom/performance/PerformanceResourceTiming.cpp | 27 ++++++++ dom/performance/PerformanceResourceTiming.h | 3 + dom/performance/PerformanceServerTiming.cpp | 69 +++++++++++++++++++ dom/performance/PerformanceServerTiming.h | 58 ++++++++++++++++ dom/performance/PerformanceTiming.cpp | 14 ++++ dom/performance/PerformanceTiming.h | 3 + dom/performance/moz.build | 2 + .../mochitest/general/test_interfaces.js | 2 + dom/webidl/PerformanceResourceTiming.webidl | 5 ++ dom/webidl/PerformanceServerTiming.webidl | 20 ++++++ dom/webidl/moz.build | 1 + .../test_serviceworker_interfaces.js | 2 + dom/workers/test/test_worker_interfaces.js | 2 + 13 files changed, 208 insertions(+) create mode 100644 dom/performance/PerformanceServerTiming.cpp create mode 100644 dom/performance/PerformanceServerTiming.h create mode 100644 dom/webidl/PerformanceServerTiming.webidl diff --git a/dom/performance/PerformanceResourceTiming.cpp b/dom/performance/PerformanceResourceTiming.cpp index f08f320ca729..8491318bfaf7 100644 --- a/dom/performance/PerformanceResourceTiming.cpp +++ b/dom/performance/PerformanceResourceTiming.cpp @@ -6,6 +6,7 @@ #include "PerformanceResourceTiming.h" #include "mozilla/dom/PerformanceResourceTimingBinding.h" +#include "nsArrayUtils.h" using namespace mozilla::dom; @@ -108,3 +109,29 @@ PerformanceResourceTiming::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSize mInitiatorType.SizeOfExcludingThisIfUnshared(aMallocSizeOf) + mNextHopProtocol.SizeOfExcludingThisIfUnshared(aMallocSizeOf); } + +void +PerformanceResourceTiming::GetServerTiming( + nsTArray>& aRetval) +{ + aRetval.Clear(); + + nsCOMPtr serverTimingArray = mTiming->GetServerTiming(); + if (!serverTimingArray) { + return; + } + + uint32_t length = 0; + if (NS_FAILED(serverTimingArray->GetLength(&length))) { + return; + } + + for (uint32_t index = 0; index < length; ++index) { + nsCOMPtr serverTiming = + do_QueryElementAt(serverTimingArray, index); + MOZ_ASSERT(serverTiming); + + aRetval.AppendElement( + new PerformanceServerTiming(GetParentObject(), serverTiming)); + } +} diff --git a/dom/performance/PerformanceResourceTiming.h b/dom/performance/PerformanceResourceTiming.h index b768528ff97d..9a69efc75596 100644 --- a/dom/performance/PerformanceResourceTiming.h +++ b/dom/performance/PerformanceResourceTiming.h @@ -12,6 +12,7 @@ #include "nsITimedChannel.h" #include "Performance.h" #include "PerformanceEntry.h" +#include "PerformanceServerTiming.h" #include "PerformanceTiming.h" namespace mozilla { @@ -178,6 +179,8 @@ public: size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override; + void GetServerTiming(nsTArray>& aRetval); + protected: virtual ~PerformanceResourceTiming(); void SetPropertiesFromChannel(nsIHttpChannel* aChannel); diff --git a/dom/performance/PerformanceServerTiming.cpp b/dom/performance/PerformanceServerTiming.cpp new file mode 100644 index 000000000000..cd5846b39b20 --- /dev/null +++ b/dom/performance/PerformanceServerTiming.cpp @@ -0,0 +1,69 @@ +/* -*- 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 "PerformanceServerTiming.h" + +#include "mozilla/dom/PerformanceServerTimingBinding.h" +#include "mozilla/Unused.h" +#include "nsITimedChannel.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PerformanceServerTiming, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(PerformanceServerTiming) +NS_IMPL_CYCLE_COLLECTING_RELEASE(PerformanceServerTiming) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceServerTiming) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +JSObject* +PerformanceServerTiming::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return mozilla::dom::PerformanceServerTimingBinding::Wrap(aCx, this, aGivenProto); +} + +void +PerformanceServerTiming::GetName(nsAString& aName) const +{ + if (!mServerTiming) { + return; + } + + nsAutoCString name; + Unused << mServerTiming->GetName(name); + aName.Assign(NS_ConvertUTF8toUTF16(name)); +} + +DOMHighResTimeStamp +PerformanceServerTiming::Duration() const +{ + if (!mServerTiming) { + return 0; + } + + double duration = 0; + Unused << mServerTiming->GetDuration(&duration); + return duration; +} + +void +PerformanceServerTiming::GetDescription(nsAString& aDescription) const +{ + if (!mServerTiming) { + return; + } + + nsAutoCString description; + Unused << mServerTiming->GetDescription(description); + aDescription.Assign(NS_ConvertUTF8toUTF16(description)); +} + +} // dom namespace +} // mozilla namespace diff --git a/dom/performance/PerformanceServerTiming.h b/dom/performance/PerformanceServerTiming.h new file mode 100644 index 000000000000..2da6144c01da --- /dev/null +++ b/dom/performance/PerformanceServerTiming.h @@ -0,0 +1,58 @@ +/* -*- 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_PerformanceServerTiming_h +#define mozilla_dom_PerformanceServerTiming_h + +#include "mozilla/Attributes.h" +#include "nsWrapperCache.h" +#include "nsString.h" + +class nsIServerTiming; +class nsISupports; + +namespace mozilla { +namespace dom { + +class PerformanceServerTiming final : public nsISupports, + public nsWrapperCache +{ +public: + PerformanceServerTiming(nsISupports* aParent, nsIServerTiming* aServerTiming) + : mParent(aParent) + , mServerTiming(aServerTiming) + { + MOZ_ASSERT(mServerTiming); + } + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PerformanceServerTiming) + + JSObject* + WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + + nsISupports* GetParentObject() const + { + return mParent; + } + + void GetName(nsAString& aName) const; + + DOMHighResTimeStamp Duration() const; + + void GetDescription(nsAString& aDescription) const; + +private: + ~PerformanceServerTiming() = default; + + nsCOMPtr mParent; + nsCOMPtr mServerTiming; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_PerformanceServerTiming_h diff --git a/dom/performance/PerformanceTiming.cpp b/dom/performance/PerformanceTiming.cpp index 384a420e6166..235698b2b244 100644 --- a/dom/performance/PerformanceTiming.cpp +++ b/dom/performance/PerformanceTiming.cpp @@ -109,6 +109,8 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel) // ServiceWorker interception responseStart? aChannel->GetHandleFetchEventEnd(&mWorkerResponseEnd); + aChannel->GetServerTiming(getter_AddRefs(mServerTiming)); + // The performance timing api essentially requires that the event timestamps // have a strict relation with each other. The truth, however, is the browser // engages in a number of speculative activities that sometimes mean connections @@ -520,5 +522,17 @@ PerformanceTiming::IsTopLevelContentDocument() const return rootItem->ItemType() == nsIDocShellTreeItem::typeContent; } +already_AddRefed +PerformanceTiming::GetServerTiming() const +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() || + nsContentUtils::ShouldResistFingerprinting()) { + return nullptr; + } + + nsCOMPtr serverTiming = mServerTiming; + return serverTiming.forget(); +} + } // dom namespace } // mozilla namespace diff --git a/dom/performance/PerformanceTiming.h b/dom/performance/PerformanceTiming.h index e904e20e2cd9..4f5019586c5e 100644 --- a/dom/performance/PerformanceTiming.h +++ b/dom/performance/PerformanceTiming.h @@ -260,6 +260,8 @@ public: return GetDOMTiming()->GetTimeToNonBlankPaint(); } + already_AddRefed GetServerTiming() const; + private: ~PerformanceTiming(); @@ -307,6 +309,7 @@ private: bool mReportCrossOriginRedirect; bool mSecureConnection; + nsCOMPtr mServerTiming; }; } // namespace dom diff --git a/dom/performance/moz.build b/dom/performance/moz.build index 53053f3b1f01..63e273a57de8 100644 --- a/dom/performance/moz.build +++ b/dom/performance/moz.build @@ -17,6 +17,7 @@ EXPORTS.mozilla.dom += [ 'PerformanceObserver.h', 'PerformanceObserverEntryList.h', 'PerformanceResourceTiming.h', + 'PerformanceServerTiming.h', 'PerformanceService.h', 'PerformanceTiming.h', ] @@ -32,6 +33,7 @@ UNIFIED_SOURCES += [ 'PerformanceObserver.cpp', 'PerformanceObserverEntryList.cpp', 'PerformanceResourceTiming.cpp', + 'PerformanceServerTiming.cpp', 'PerformanceService.cpp', 'PerformanceTiming.cpp', 'PerformanceWorker.cpp', diff --git a/dom/tests/mochitest/general/test_interfaces.js b/dom/tests/mochitest/general/test_interfaces.js index 259f0d186867..a9a16e7cc9f7 100644 --- a/dom/tests/mochitest/general/test_interfaces.js +++ b/dom/tests/mochitest/general/test_interfaces.js @@ -732,6 +732,8 @@ var interfaceNamesInGlobalScope = "PerformanceObserverEntryList", // IMPORTANT: Do not change this list without review from a DOM peer! "PerformanceResourceTiming", +// IMPORTANT: Do not change this list without review from a DOM peer! + "PerformanceServerTiming", // IMPORTANT: Do not change this list without review from a DOM peer! "PerformanceTiming", // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/dom/webidl/PerformanceResourceTiming.webidl b/dom/webidl/PerformanceResourceTiming.webidl index 112228325a1f..f155e6c7b497 100644 --- a/dom/webidl/PerformanceResourceTiming.webidl +++ b/dom/webidl/PerformanceResourceTiming.webidl @@ -32,5 +32,10 @@ interface PerformanceResourceTiming : PerformanceEntry readonly attribute unsigned long long encodedBodySize; readonly attribute unsigned long long decodedBodySize; + // TODO: Use FrozenArray once available. (Bug 1236777) + // readonly attribute FrozenArray serverTiming; + [Frozen, Cached, Pure] + readonly attribute sequence serverTiming; + jsonifier; }; diff --git a/dom/webidl/PerformanceServerTiming.webidl b/dom/webidl/PerformanceServerTiming.webidl new file mode 100644 index 000000000000..32e5938fb6c2 --- /dev/null +++ b/dom/webidl/PerformanceServerTiming.webidl @@ -0,0 +1,20 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + * + * The origin of this IDL file is + * https://w3c.github.io/server-timing/ + * + * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * liability, trademark and document use rules apply. + */ + +[Exposed=(Window,Worker)] +interface PerformanceServerTiming { + readonly attribute DOMString name; + readonly attribute DOMHighResTimeStamp duration; + readonly attribute DOMString description; + + jsonifier; +}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 3929d2b9d928..ad5051ef1138 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -725,6 +725,7 @@ WEBIDL_FILES = [ 'PerformanceObserver.webidl', 'PerformanceObserverEntryList.webidl', 'PerformanceResourceTiming.webidl', + 'PerformanceServerTiming.webidl', 'PerformanceTiming.webidl', 'PeriodicWave.webidl', 'Permissions.webidl', diff --git a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js index fd827eb732d2..38b079eea424 100644 --- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js +++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js @@ -188,6 +188,8 @@ var interfaceNamesInGlobalScope = "PerformanceObserver", // IMPORTANT: Do not change this list without review from a DOM peer! "PerformanceObserverEntryList", +// IMPORTANT: Do not change this list without review from a DOM peer! + "PerformanceServerTiming", // IMPORTANT: Do not change this list without review from a DOM peer! "ProgressEvent", // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/dom/workers/test/test_worker_interfaces.js b/dom/workers/test/test_worker_interfaces.js index 27dedfdfde8a..77cabb9047e0 100644 --- a/dom/workers/test/test_worker_interfaces.js +++ b/dom/workers/test/test_worker_interfaces.js @@ -182,6 +182,8 @@ var interfaceNamesInGlobalScope = "PerformanceObserver", // IMPORTANT: Do not change this list without review from a DOM peer! "PerformanceObserverEntryList", +// IMPORTANT: Do not change this list without review from a DOM peer! + "PerformanceServerTiming", // IMPORTANT: Do not change this list without review from a DOM peer! "ProgressEvent", // IMPORTANT: Do not change this list without review from a DOM peer!