Bug 1322396 - report external resources of documents when flushing use counters in tests; r=dholbert
authorNathan Froyd <froydnj@mozilla.com>
Wed, 11 Jan 2017 09:52:23 -0500
changeset 328878 ba1cd6819a224d017d450eb0cdf9d550d7aef77f
parent 328877 4cc69cb3bcb6f6d5d68b5b74d972351301766072
child 328879 2e5f60f217b5331c32a8b718750130a60ce07ff3
push id85579
push usernfroyd@mozilla.com
push dateWed, 11 Jan 2017 14:52:31 +0000
treeherdermozilla-inbound@ba1cd6819a22 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
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 1322396 - report external resources of documents when flushing use counters in tests; r=dholbert Our use counter tests force reporting of use counters from documents to make the tests more deterministic: relying on the default report-at-document-destruction behavior would introduce any number of intermittents. However, documents may have any number of external resource documents, and we have no mechanism for forcing a deterministic reporting of the use counters from those documents. Relying on those external resources to have been destroyed (and thereby reported their use counters) when we examine the values of the use counters in question is a recipe for intermittent failures. Therefore, we introduce an optional report kind for use counter reporting: if a document is reporting its use counters for the purposes of a test, we will also report the use counters for the document's external resource documents. This change makes everything more deterministic.
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -4021,17 +4021,20 @@ NS_IMETHODIMP
 nsDOMWindowUtils::ForceUseCounterFlush(nsIDOMNode *aNode)
   if (nsCOMPtr<nsIDocument> doc = do_QueryInterface(aNode)) {
     mozilla::css::ImageLoader* loader = doc->StyleImageLoader();
-    static_cast<nsDocument*>(doc.get())->ReportUseCounters();
+    // Flush the document and any external documents that it depends on.
+    const auto reportKind
+      = nsDocument::UseCounterReportKind::eIncludeExternalResources;
+    static_cast<nsDocument*>(doc.get())->ReportUseCounters(reportKind);
     return NS_OK;
   if (nsCOMPtr<nsIContent> content = do_QueryInterface(aNode)) {
     if (HTMLImageElement* img = HTMLImageElement::FromContent(content)) {
       return NS_OK;
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -12299,26 +12299,39 @@ MightBeAboutOrChromeScheme(nsIURI* aURI)
   bool isAbout = true;
   bool isChrome = true;
   aURI->SchemeIs("about", &isAbout);
   aURI->SchemeIs("chrome", &isChrome);
   return isAbout || isChrome;
+static bool
+ReportExternalResourceUseCounters(nsIDocument* aDocument, void* aData)
+  const auto reportKind
+    = nsDocument::UseCounterReportKind::eIncludeExternalResources;
+  static_cast<nsDocument*>(aDocument)->ReportUseCounters(reportKind);
+  return true;
+nsDocument::ReportUseCounters(UseCounterReportKind aKind)
   static const bool sDebugUseCounters = false;
   if (mReportedUseCounters) {
   mReportedUseCounters = true;
+  if (aKind == UseCounterReportKind::eIncludeExternalResources) {
+    EnumerateExternalResources(ReportExternalResourceUseCounters, nullptr);
+  }
   if (Telemetry::HistogramUseCounterCount > 0 &&
       (IsContentDocument() || IsResourceDoc())) {
     nsCOMPtr<nsIURI> uri;
     if (!uri || MightBeAboutOrChromeScheme(uri)) {
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -769,17 +769,29 @@ public:
   virtual void SetValueMissingState(const nsAString& aName, bool aValue) override;
   // for radio group
   nsRadioGroupStruct* GetRadioGroup(const nsAString& aName) const;
   nsRadioGroupStruct* GetOrCreateRadioGroup(const nsAString& aName);
   virtual nsViewportInfo GetViewportInfo(const mozilla::ScreenIntSize& aDisplaySize) override;
-  void ReportUseCounters();
+  enum class UseCounterReportKind {
+    // Flush the document's use counters only; the use counters for any
+    // external resource documents will be flushed when the external
+    // resource documents themselves are destroyed.
+    eDefault,
+    // Flush use counters for the document and for its external resource
+    // documents. (Should only be necessary for tests, where we need
+    // flushing to happen synchronously and deterministically.)
+    eIncludeExternalResources,
+  };
+  void ReportUseCounters(UseCounterReportKind aKind = UseCounterReportKind::eDefault);
   virtual void AddIntersectionObserver(
     mozilla::dom::DOMIntersectionObserver* aObserver) override;
   virtual void RemoveIntersectionObserver(
     mozilla::dom::DOMIntersectionObserver* aObserver) override;
   virtual void UpdateIntersectionObservations() override;
   virtual void ScheduleIntersectionObserverNotification() override;
   virtual void NotifyIntersectionObservers() override;