Bug 1344893 - Part 1: Report Navigation Timing into Telemetry. r=smaug, data-review=bsmedberg
authorWei-Cheng Pan <wpan@mozilla.com>
Wed, 19 Apr 2017 02:00:00 -0400
changeset 565166 3559898682b966f7e0110639c3e5c7da2382fdd3
parent 565165 12e148dcab63465fc8e5414649156550632ecf91
child 565167 3e22ac1beeda05bb7954434d37241438859fb557
push id54802
push userdgottwald@mozilla.com
push dateWed, 19 Apr 2017 15:26:27 +0000
reviewerssmaug
bugs1344893
milestone55.0a1
Bug 1344893 - Part 1: Report Navigation Timing into Telemetry. r=smaug, data-review=bsmedberg We only need metric from top level content document, but we dont have any information about it in nsDOMNavigationTiming, so I add a weak reference which points to nsDocShell. MozReview-Commit-ID: GiJigRLYHNV
docshell/base/nsDocShell.cpp
dom/base/nsDOMNavigationTiming.cpp
dom/base/nsDOMNavigationTiming.h
image/SVGDocumentWrapper.cpp
toolkit/components/telemetry/Histograms.json
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1783,17 +1783,17 @@ nsDocShell::MaybeInitTiming()
       mScriptGlobal->AsOuter()->GetCurrentInnerWindow();
     if (innerWin && innerWin->GetPerformance()) {
       mTiming = innerWin->GetPerformance()->GetDOMTiming();
       mBlankTiming = false;
     }
   }
 
   if (!mTiming) {
-    mTiming = new nsDOMNavigationTiming();
+    mTiming = new nsDOMNavigationTiming(this);
     canBeReset = true;
   }
 
   mTiming->NotifyNavigationStart(
     mIsActive ? nsDOMNavigationTiming::DocShellState::eActive
               : nsDOMNavigationTiming::DocShellState::eInactive);
 
   return canBeReset;
--- a/dom/base/nsDOMNavigationTiming.cpp
+++ b/dom/base/nsDOMNavigationTiming.cpp
@@ -4,29 +4,33 @@
  * 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 "nsDOMNavigationTiming.h"
 
 #include "GeckoProfiler.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
+#include "nsDocShell.h"
+#include "nsIDocShellTreeItem.h"
 #include "nsIScriptSecurityManager.h"
 #include "prtime.h"
 #include "nsIURI.h"
 #include "nsPrintfCString.h"
 #include "mozilla/dom/PerformanceNavigation.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
 
-nsDOMNavigationTiming::nsDOMNavigationTiming()
+nsDOMNavigationTiming::nsDOMNavigationTiming(nsDocShell* aDocShell)
 {
   Clear();
+
+  mDocShell = aDocShell;
 }
 
 nsDOMNavigationTiming::~nsDOMNavigationTiming()
 {
 }
 
 void
 nsDOMNavigationTiming::Clear()
@@ -113,25 +117,35 @@ nsDOMNavigationTiming::NotifyUnloadEvent
 }
 
 void
 nsDOMNavigationTiming::NotifyLoadEventStart()
 {
   if (!mLoadEventStartSet) {
     mLoadEventStart = DurationFromStart();
     mLoadEventStartSet = true;
+
+    if (IsTopLevelContentDocument()) {
+      Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_LOAD_EVENT_START_MS,
+                                     mNavigationStartTimeStamp);
+    }
   }
 }
 
 void
 nsDOMNavigationTiming::NotifyLoadEventEnd()
 {
   if (!mLoadEventEndSet) {
     mLoadEventEnd = DurationFromStart();
     mLoadEventEndSet = true;
+
+    if (IsTopLevelContentDocument()) {
+      Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_LOAD_EVENT_END_MS,
+                                     mNavigationStartTimeStamp);
+    }
   }
 }
 
 void
 nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, TimeStamp aValue)
 {
   if (!mDOMLoadingSet) {
     mLoadedURI = aURI;
@@ -142,56 +156,81 @@ nsDOMNavigationTiming::SetDOMLoadingTime
 
 void
 nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI)
 {
   if (!mDOMLoadingSet) {
     mLoadedURI = aURI;
     mDOMLoading = DurationFromStart();
     mDOMLoadingSet = true;
+
+    if (IsTopLevelContentDocument()) {
+      Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_LOADING_MS,
+                                     mNavigationStartTimeStamp);
+    }
   }
 }
 
 void
 nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI* aURI)
 {
   if (!mDOMInteractiveSet) {
     mLoadedURI = aURI;
     mDOMInteractive = DurationFromStart();
     mDOMInteractiveSet = true;
+
+    if (IsTopLevelContentDocument()) {
+      Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_INTERACTIVE_MS,
+                                     mNavigationStartTimeStamp);
+    }
   }
 }
 
 void
 nsDOMNavigationTiming::NotifyDOMComplete(nsIURI* aURI)
 {
   if (!mDOMCompleteSet) {
     mLoadedURI = aURI;
     mDOMComplete = DurationFromStart();
     mDOMCompleteSet = true;
+
+    if (IsTopLevelContentDocument()) {
+      Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_COMPLETE_MS,
+                                     mNavigationStartTimeStamp);
+    }
   }
 }
 
 void
 nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI)
 {
   if (!mDOMContentLoadedEventStartSet) {
     mLoadedURI = aURI;
     mDOMContentLoadedEventStart = DurationFromStart();
     mDOMContentLoadedEventStartSet = true;
+
+    if (IsTopLevelContentDocument()) {
+      Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_CONTENT_LOADED_START_MS,
+                                     mNavigationStartTimeStamp);
+    }
   }
 }
 
 void
 nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI)
 {
   if (!mDOMContentLoadedEventEndSet) {
     mLoadedURI = aURI;
     mDOMContentLoadedEventEnd = DurationFromStart();
     mDOMContentLoadedEventEndSet = true;
+
+    if (IsTopLevelContentDocument()) {
+      Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_CONTENT_LOADED_END_MS,
+                                     mNavigationStartTimeStamp);
+    }
   }
 }
 
 void
 nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mNavigationStartTimeStamp.IsNull());
@@ -244,8 +283,22 @@ nsDOMNavigationTiming::GetUnloadEventEnd
 {
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
   if (NS_SUCCEEDED(rv)) {
     return mUnloadEnd;
   }
   return 0;
 }
+
+bool
+nsDOMNavigationTiming::IsTopLevelContentDocument() const
+{
+  if (!mDocShell) {
+    return false;
+  }
+  nsCOMPtr<nsIDocShellTreeItem> rootItem;
+  Unused << mDocShell->GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
+  if (rootItem.get() != static_cast<nsIDocShellTreeItem*>(mDocShell.get())) {
+    return false;
+  }
+  return rootItem->ItemType() == nsIDocShellTreeItem::typeContent;
+}
--- a/dom/base/nsDOMNavigationTiming.h
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -4,34 +4,36 @@
  * 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 nsDOMNavigationTiming_h___
 #define nsDOMNavigationTiming_h___
 
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
+#include "mozilla/WeakPtr.h"
 #include "mozilla/TimeStamp.h"
 
+class nsDocShell;
 class nsIURI;
 
 typedef unsigned long long DOMTimeMilliSec;
 typedef double DOMHighResTimeStamp;
 
 class nsDOMNavigationTiming final
 {
 public:
   enum Type {
     TYPE_NAVIGATE = 0,
     TYPE_RELOAD = 1,
     TYPE_BACK_FORWARD = 2,
     TYPE_RESERVED = 255,
   };
 
-  nsDOMNavigationTiming();
+  explicit nsDOMNavigationTiming(nsDocShell* aDocShell);
 
   NS_INLINE_DECL_REFCOUNTING(nsDOMNavigationTiming)
 
   Type GetType() const
   {
     return mNavigationType;
   }
 
@@ -115,16 +117,20 @@ public:
   }
 
 private:
   nsDOMNavigationTiming(const nsDOMNavigationTiming &) = delete;
   ~nsDOMNavigationTiming();
 
   void Clear();
 
+  bool IsTopLevelContentDocument() const;
+
+  mozilla::WeakPtr<nsDocShell> mDocShell;
+
   nsCOMPtr<nsIURI> mUnloadedURI;
   nsCOMPtr<nsIURI> mLoadedURI;
 
   Type mNavigationType;
   DOMHighResTimeStamp mNavigationStartHighRes;
   mozilla::TimeStamp mNavigationStartTimeStamp;
   mozilla::TimeStamp mNonBlankPaintTimeStamp;
   DOMTimeMilliSec DurationFromStart();
--- a/image/SVGDocumentWrapper.cpp
+++ b/image/SVGDocumentWrapper.cpp
@@ -356,17 +356,17 @@ SVGDocumentWrapper::SetupViewer(nsIReque
   // The timeline(DocumentTimeline, used in CSS animation) of this SVG
   // document needs this navigation timing object for time computation, such
   // as to calculate current time stamp based on the start time of navigation
   // time object.
   //
   // For a root document, DocShell would do these sort of things
   // automatically. Since there is no DocShell for this wrapped SVG document,
   // we must set it up manually.
-  RefPtr<nsDOMNavigationTiming> timing = new nsDOMNavigationTiming();
+  RefPtr<nsDOMNavigationTiming> timing = new nsDOMNavigationTiming(nullptr);
   timing->NotifyNavigationStart(nsDOMNavigationTiming::DocShellState::eInactive);
   viewer->SetNavigationTiming(timing);
 
   nsCOMPtr<nsIParser> parser = do_QueryInterface(listener);
   NS_ENSURE_TRUE(parser, NS_ERROR_UNEXPECTED);
 
   // XML-only, because this is for SVG content
   nsCOMPtr<nsIContentSink> sink = parser->GetContentSink();
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -11343,10 +11343,73 @@
   },
   "DISPLAY_ITEM_USAGE_COUNT": {
     "alert_emails": ["mchang@mozilla.com"],
     "bug_numbers": [1353521],
     "expires_in_version": "70",
     "kind": "enumerated",
     "n_values": 99,
     "description": "Count of which display items are being used by type id"
+  },
+  "TIME_TO_DOM_LOADING_MS": {
+    "alert_emails": ["wpan@mozilla.com"],
+    "expires_in_version": "60",
+    "kind": "exponential",
+    "high": 50000,
+    "n_buckets": 100,
+    "bug_numbers": [1344893],
+    "description": "Time in milliseconds from navigationStart to domLoading."
+  },
+  "TIME_TO_DOM_INTERACTIVE_MS": {
+    "alert_emails": ["wpan@mozilla.com"],
+    "expires_in_version": "60",
+    "kind": "exponential",
+    "high": 50000,
+    "n_buckets": 100,
+    "bug_numbers": [1344893],
+    "description": "Time in milliseconds from navigationStart to domInteractive."
+  },
+  "TIME_TO_DOM_CONTENT_LOADED_START_MS": {
+    "alert_emails": ["wpan@mozilla.com"],
+    "expires_in_version": "60",
+    "kind": "exponential",
+    "high": 50000,
+    "n_buckets": 100,
+    "bug_numbers": [1344893],
+    "description": "Time in milliseconds from navigationStart to domContentLoadedEventStart."
+  },
+  "TIME_TO_DOM_CONTENT_LOADED_END_MS": {
+    "alert_emails": ["wpan@mozilla.com"],
+    "expires_in_version": "60",
+    "kind": "exponential",
+    "high": 50000,
+    "n_buckets": 100,
+    "bug_numbers": [1344893],
+    "description": "Time in milliseconds from navigationStart to domContentLoadedEventEnd."
+  },
+  "TIME_TO_DOM_COMPLETE_MS": {
+    "alert_emails": ["wpan@mozilla.com"],
+    "expires_in_version": "60",
+    "kind": "exponential",
+    "high": 50000,
+    "n_buckets": 100,
+    "bug_numbers": [1344893],
+    "description": "Time in milliseconds from navigationStart to domComplete."
+  },
+  "TIME_TO_LOAD_EVENT_START_MS": {
+    "alert_emails": ["wpan@mozilla.com"],
+    "expires_in_version": "60",
+    "kind": "exponential",
+    "high": 50000,
+    "n_buckets": 100,
+    "bug_numbers": [1344893],
+    "description": "Time in milliseconds from navigationStart to loadEventStart."
+  },
+  "TIME_TO_LOAD_EVENT_END_MS": {
+    "alert_emails": ["wpan@mozilla.com"],
+    "expires_in_version": "60",
+    "kind": "exponential",
+    "high": 50000,
+    "n_buckets": 100,
+    "bug_numbers": [1344893],
+    "description": "Time in milliseconds from navigationStart to loadEventEnd."
   }
 }