Bug 1423495 - Part 1: Implement PerformanceServerTiming. r=baku
☠☠ backed out by 48053e1b869e ☠ ☠
authorKershaw Chang <kechang@mozilla.com>
Wed, 10 Jan 2018 04:01:00 -0500
changeset 452932 aca79713b901610cec0bce7dfac13d4c500f4b9d
parent 452931 a30d2216e0b9c8fc902f5e1704eafabab828fcff
child 452933 f7667f5a63af3664632c9c175ebb2b07b65bda89
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1423495
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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
dom/performance/PerformanceResourceTiming.h
dom/performance/PerformanceServerTiming.cpp
dom/performance/PerformanceServerTiming.h
dom/performance/PerformanceTiming.cpp
dom/performance/PerformanceTiming.h
dom/performance/moz.build
dom/tests/mochitest/general/test_interfaces.js
dom/webidl/PerformanceResourceTiming.webidl
dom/webidl/PerformanceServerTiming.webidl
dom/webidl/moz.build
dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
dom/workers/test/test_worker_interfaces.js
--- a/dom/performance/PerformanceResourceTiming.cpp
+++ b/dom/performance/PerformanceResourceTiming.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "nsArrayUtils.h"
 
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformanceResourceTiming,
                                    PerformanceEntry,
                                    mTiming)
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceResourceTiming,
@@ -103,8 +104,34 @@ PerformanceResourceTiming::SizeOfIncludi
 
 size_t
 PerformanceResourceTiming::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   return PerformanceEntry::SizeOfExcludingThis(aMallocSizeOf) +
          mInitiatorType.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
          mNextHopProtocol.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
 }
+
+void
+PerformanceResourceTiming::GetServerTiming(
+                            nsTArray<RefPtr<PerformanceServerTiming>>& aRetval)
+{
+  aRetval.Clear();
+
+  nsCOMPtr<nsIArray> 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<nsIServerTiming> serverTiming =
+      do_QueryElementAt(serverTimingArray, index);
+    MOZ_ASSERT(serverTiming);
+
+    aRetval.AppendElement(
+      new PerformanceServerTiming(GetParentObject(), serverTiming));
+  }
+}
--- a/dom/performance/PerformanceResourceTiming.h
+++ b/dom/performance/PerformanceResourceTiming.h
@@ -7,16 +7,17 @@
 #ifndef mozilla_dom_PerformanceResourceTiming_h___
 #define mozilla_dom_PerformanceResourceTiming_h___
 
 #include "nsCOMPtr.h"
 #include "nsIChannel.h"
 #include "nsITimedChannel.h"
 #include "Performance.h"
 #include "PerformanceEntry.h"
+#include "PerformanceServerTiming.h"
 #include "PerformanceTiming.h"
 
 namespace mozilla {
 namespace dom {
 
 // http://www.w3.org/TR/resource-timing/#performanceresourcetiming
 class PerformanceResourceTiming : public PerformanceEntry
 {
@@ -173,16 +174,18 @@ public:
   void SetDecodedBodySize(uint64_t aDecodedBodySize)
   {
     mDecodedBodySize = aDecodedBodySize;
   }
 
   size_t
   SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
 
+  void GetServerTiming(nsTArray<RefPtr<PerformanceServerTiming>>& aRetval);
+
 protected:
   virtual ~PerformanceResourceTiming();
   void SetPropertiesFromChannel(nsIHttpChannel* aChannel);
 
   size_t
   SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
 
   nsString mInitiatorType;
new file mode 100644
--- /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<JSObject*> 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
new file mode 100644
--- /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<JSObject*> aGivenProto) override;
+
+  nsISupports* GetParentObject() const
+  {
+    return mParent;
+  }
+
+  void GetName(nsAString& aName) const;
+
+  DOMHighResTimeStamp Duration() const;
+
+  void GetDescription(nsAString& aDescription) const;
+
+private:
+  ~PerformanceServerTiming() = default;
+
+  nsCOMPtr<nsISupports> mParent;
+  nsCOMPtr<nsIServerTiming> mServerTiming;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_PerformanceServerTiming_h
--- a/dom/performance/PerformanceTiming.cpp
+++ b/dom/performance/PerformanceTiming.cpp
@@ -104,16 +104,18 @@ PerformanceTiming::InitializeTimingInfo(
     aChannel->GetCacheReadEnd(&mCacheReadEnd);
 
     aChannel->GetDispatchFetchEventStart(&mWorkerStart);
     aChannel->GetHandleFetchEventStart(&mWorkerRequestStart);
     // TODO: Track when FetchEvent.respondWith() promise resolves as
     //       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
     // and lookups begin at different times. Workaround that here by clamping
     // these values to what we expect FetchStart to be.  This means the later of
     // AsyncOpen or WorkerStart times.
     if (!mAsyncOpen.IsNull()) {
       // We want to clamp to the expected FetchStart value.  This is later of
@@ -515,10 +517,22 @@ PerformanceTiming::IsTopLevelContentDocu
   nsCOMPtr<nsIDocShellTreeItem> rootItem;
   Unused << docShell->GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
   if (rootItem.get() != static_cast<nsIDocShellTreeItem*>(docShell.get())) {
     return false;
   }
   return rootItem->ItemType() == nsIDocShellTreeItem::typeContent;
 }
 
+already_AddRefed<nsIArray>
+PerformanceTiming::GetServerTiming() const
+{
+  if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
+      nsContentUtils::ShouldResistFingerprinting()) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIArray> serverTiming = mServerTiming;
+  return serverTiming.forget();
+}
+
 } // dom namespace
 } // mozilla namespace
--- a/dom/performance/PerformanceTiming.h
+++ b/dom/performance/PerformanceTiming.h
@@ -255,16 +255,18 @@ public:
   {
     if (!nsContentUtils::IsPerformanceTimingEnabled() ||
         nsContentUtils::ShouldResistFingerprinting()) {
       return 0;
     }
     return GetDOMTiming()->GetTimeToNonBlankPaint();
   }
 
+  already_AddRefed<nsIArray> GetServerTiming() const;
+
 private:
   ~PerformanceTiming();
 
   bool IsInitialized() const;
   void InitializeTimingInfo(nsITimedChannel* aChannel);
 
   bool IsTopLevelContentDocument() const;
 
@@ -302,14 +304,15 @@ private:
   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;
 
   bool mSecureConnection;
+  nsCOMPtr<nsIArray> mServerTiming;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_PerformanceTiming_h
--- a/dom/performance/moz.build
+++ b/dom/performance/moz.build
@@ -12,31 +12,33 @@ EXPORTS.mozilla.dom += [
     'PerformanceEntry.h',
     'PerformanceMark.h',
     'PerformanceMeasure.h',
     'PerformanceNavigation.h',
     'PerformanceNavigationTiming.h',
     'PerformanceObserver.h',
     'PerformanceObserverEntryList.h',
     'PerformanceResourceTiming.h',
+    'PerformanceServerTiming.h',
     'PerformanceService.h',
     'PerformanceTiming.h',
 ]
 
 UNIFIED_SOURCES += [
     'Performance.cpp',
     'PerformanceEntry.cpp',
     'PerformanceMainThread.cpp',
     'PerformanceMark.cpp',
     'PerformanceMeasure.cpp',
     'PerformanceNavigation.cpp',
     'PerformanceNavigationTiming.cpp',
     'PerformanceObserver.cpp',
     'PerformanceObserverEntryList.cpp',
     'PerformanceResourceTiming.cpp',
+    'PerformanceServerTiming.cpp',
     'PerformanceService.cpp',
     'PerformanceTiming.cpp',
     'PerformanceWorker.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/workers',
 ]
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -728,16 +728,18 @@ var interfaceNamesInGlobalScope =
     "PerformanceNavigationTiming",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "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!
     "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!
     "PeriodicWave",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Permissions",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PermissionStatus",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/webidl/PerformanceResourceTiming.webidl
+++ b/dom/webidl/PerformanceResourceTiming.webidl
@@ -27,10 +27,15 @@ interface PerformanceResourceTiming : Pe
   readonly attribute DOMHighResTimeStamp requestStart;
   readonly attribute DOMHighResTimeStamp responseStart;
   readonly attribute DOMHighResTimeStamp responseEnd;
 
   readonly attribute unsigned long long transferSize;
   readonly attribute unsigned long long encodedBodySize;
   readonly attribute unsigned long long decodedBodySize;
 
+  // TODO: Use FrozenArray once available. (Bug 1236777)
+  // readonly attribute FrozenArray<PerformanceServerTiming> serverTiming;
+  [Frozen, Cached, Pure]
+  readonly attribute sequence<PerformanceServerTiming> serverTiming;
+
   jsonifier;
 };
new file mode 100644
--- /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;
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -720,16 +720,17 @@ WEBIDL_FILES = [
     'PerformanceEntry.webidl',
     'PerformanceMark.webidl',
     'PerformanceMeasure.webidl',
     'PerformanceNavigation.webidl',
     'PerformanceNavigationTiming.webidl',
     'PerformanceObserver.webidl',
     'PerformanceObserverEntryList.webidl',
     'PerformanceResourceTiming.webidl',
+    'PerformanceServerTiming.webidl',
     'PerformanceTiming.webidl',
     'PeriodicWave.webidl',
     'Permissions.webidl',
     'PermissionStatus.webidl',
     'Plugin.webidl',
     'PluginArray.webidl',
     'PointerEvent.webidl',
     'PopupBoxObject.webidl',
--- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
+++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
@@ -184,16 +184,18 @@ var interfaceNamesInGlobalScope =
     "PerformanceMark",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceMeasure",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "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!
     "PushEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PushManager",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PushMessageData",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/workers/test/test_worker_interfaces.js
+++ b/dom/workers/test/test_worker_interfaces.js
@@ -178,16 +178,18 @@ var interfaceNamesInGlobalScope =
     "PerformanceMark",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceMeasure",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "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!
     "PushManager",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PushSubscription",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PushSubscriptionOptions",
 // IMPORTANT: Do not change this list without review from a DOM peer!