Bug 968923 - part 5b - add nsIDOMWindowUtils::forceUseCounterFlush; r=bz
authorNathan Froyd <froydnj@mozilla.com>
Tue, 17 Mar 2015 15:25:35 -0400
changeset 290847 8161b137af4a0146418fa216082abc8c67d5ee24
parent 290846 185b4c796b1c2432e3f801d2b5a20a95c391608f
child 290848 f62479c673154fb4d45a502b6611477cb42e18ed
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs968923
milestone43.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 968923 - part 5b - add nsIDOMWindowUtils::forceUseCounterFlush; r=bz Use counter submission normally happens at document destruction. For testing use counters, however, we need to have use counters updated in telemetry at deterministic points. Therefore, we provide a method on nsIDOMWindowUtils that forces use counters out to telemetry so we can examine them.
dom/base/nsDOMWindowUtils.cpp
dom/html/HTMLImageElement.cpp
dom/html/HTMLImageElement.h
dom/html/moz.build
dom/interfaces/base/nsIDOMWindowUtils.idl
image/Image.h
image/VectorImage.cpp
image/VectorImage.h
layout/style/ImageLoader.cpp
layout/style/ImageLoader.h
layout/style/moz.build
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -98,16 +98,19 @@
 #include "GeckoProfiler.h"
 #include "mozilla/Preferences.h"
 #include "nsIContentIterator.h"
 #include "nsIDOMStyleSheet.h"
 #include "nsIStyleSheet.h"
 #include "nsIStyleSheetService.h"
 #include "nsContentPermissionHelper.h"
 #include "nsNetUtil.h"
+#include "nsDocument.h"
+#include "HTMLImageElement.h"
+#include "mozilla/css/ImageLoader.h"
 
 #ifdef XP_WIN
 #undef GetClassName
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
@@ -3915,16 +3918,40 @@ NS_IMETHODIMP
 nsDOMWindowUtils::LeaveChaosMode()
 {
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
   ChaosMode::leaveChaosMode();
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMWindowUtils::ForceUseCounterFlush(nsIDOMNode *aNode)
+{
+  MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
+  NS_ENSURE_ARG_POINTER(aNode);
+
+  if (nsCOMPtr<nsIDocument> doc = do_QueryInterface(aNode)) {
+    mozilla::css::ImageLoader* loader = doc->StyleImageLoader();
+    loader->FlushUseCounters();
+
+    static_cast<nsDocument*>(doc.get())->ReportUseCounters();
+    return NS_OK;
+  }
+
+  if (nsCOMPtr<nsIContent> content = do_QueryInterface(aNode)) {
+    if (HTMLImageElement* img = HTMLImageElement::FromContent(content)) {
+      img->FlushUseCounters();
+      return NS_OK;
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMWindowUtils::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType,
                                                           bool* aRetVal)
 {
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
   nsIPresShell* presShell = GetPresShell();
   if (!presShell) {
     return NS_ERROR_FAILURE;
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -6,32 +6,34 @@
 
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/HTMLImageElementBinding.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsMappedAttributes.h"
 #include "nsSize.h"
+#include "nsDocument.h"
 #include "nsIDocument.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsIScriptContext.h"
 #include "nsIURL.h"
 #include "nsIIOService.h"
 #include "nsIServiceManager.h"
 #include "nsContentUtils.h"
 #include "nsContainerFrame.h"
 #include "nsNodeInfoManager.h"
 #include "mozilla/MouseEvents.h"
 #include "nsContentPolicyUtils.h"
 #include "nsIDOMWindow.h"
 #include "nsFocusManager.h"
 #include "mozilla/dom/HTMLFormElement.h"
 #include "nsAttrValueOrString.h"
 #include "imgLoader.h"
+#include "Image.h"
 
 // Responsive images!
 #include "mozilla/dom/HTMLSourceElement.h"
 #include "mozilla/dom/ResponsiveImageSelector.h"
 
 #include "imgIContainer.h"
 #include "imgILoader.h"
 #include "imgINotificationObserver.h"
@@ -1296,11 +1298,23 @@ HTMLImageElement::DestroyContent()
 }
 
 void
 HTMLImageElement::MediaFeatureValuesChanged()
 {
   QueueImageLoadTask();
 }
 
+void
+HTMLImageElement::FlushUseCounters()
+{
+  nsCOMPtr<imgIRequest> request;
+  GetRequest(CURRENT_REQUEST, getter_AddRefs(request));
+
+  nsCOMPtr<imgIContainer> container;
+  request->GetImage(getter_AddRefs(container));
+
+  static_cast<image::Image*>(container.get())->ReportUseCounters();
+}
+
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -260,16 +260,22 @@ public:
                                 bool aIsSourceTag,
                                 const nsAString& aSrcAttr,
                                 const nsAString& aSrcsetAttr,
                                 const nsAString& aSizesAttr,
                                 const nsAString& aTypeAttr,
                                 const nsAString& aMediaAttr,
                                 nsAString& aResult);
 
+  /**
+   * If this image's src pointers to an SVG document, flush the SVG document's
+   * use counters to telemetry.  Only used for testing purposes.
+   */
+  void FlushUseCounters();
+
 protected:
   virtual ~HTMLImageElement();
 
   // Queues a task to run LoadSelectedImage pending stable state.
   //
   // Pending Bug 1076583 this is only used by the responsive image
   // algorithm (InResponsiveMode()) -- synchronous actions when just
   // using img.src will bypass this, and update source and kick off
--- a/dom/html/moz.build
+++ b/dom/html/moz.build
@@ -231,16 +231,17 @@ LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
     '/dom/canvas',
     '/dom/media/',
     '/dom/xbl',
     '/dom/xul',
     '/editor/libeditor',
     '/editor/txmgr',
+    '/image',
     '/layout/forms',
     '/layout/generic',
     '/layout/style',
     '/layout/tables',
     '/layout/xul',
     '/netwerk/base',
 ]
 
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -44,17 +44,17 @@ interface nsIDOMClientRect;
 interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
 interface nsITranslationNodeList;
 interface nsIJSRAIIHelper;
 interface nsIContentPermissionRequest;
 interface nsIObserver;
 
-[scriptable, uuid(47fa312b-2ad1-4b80-8a0a-c9822e2d1ec9)]
+[scriptable, uuid(e6d3ced6-fbce-4ea5-902a-c2055680d250)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1842,16 +1842,27 @@ interface nsIDOMWindowUtils : nsISupport
   /**
    * Returns whether the document's style set's rule processor for the
    * specified level of the cascade is shared by multiple style sets.
    * (Used by tests to ensure that certain optimizations do not regress.)
    *
    * @param aSheetType One of the nsIStyleSheetService.*_SHEET constants.
    */
   bool hasRuleProcessorUsedByMultipleStyleSets(in unsigned long aSheetType);
+
+  /*
+   * Force the use counters for the node's associated document(s) to be
+   * flushed to telemetry.  For example, a document node will flush its own
+   * counters and an image node with an SVG source will flush the SVG
+   * document's counters.  Normally, use counters are flushed to telemetry
+   * upon document destruction, but as document destruction is somewhat
+   * non-deterministic, we have this method here for more determinism when
+   * running tests.
+   */
+  void forceUseCounterFlush(in nsIDOMNode aNode);
 };
 
 [scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)]
 interface nsITranslationNodeList : nsISupports {
   readonly attribute unsigned long length;
   nsIDOMNode item(in unsigned long index);
 
   // A translation root is a block element, or an inline element
--- a/image/Image.h
+++ b/image/Image.h
@@ -224,16 +224,18 @@ public:
 
   virtual void SetInnerWindowID(uint64_t aInnerWindowId) = 0;
   virtual uint64_t InnerWindowID() const = 0;
 
   virtual bool HasError() = 0;
   virtual void SetHasError() = 0;
 
   virtual ImageURL* GetURI() = 0;
+
+  virtual void ReportUseCounters() { }
 };
 
 class ImageResource : public Image
 {
 public:
   already_AddRefed<ProgressTracker> GetProgressTracker() override
   {
     nsRefPtr<ProgressTracker> progressTracker = mProgressTracker;
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -27,16 +27,17 @@
 #include "nsSVGEffects.h" // for nsSVGRenderingObserver
 #include "nsWindowMemoryReporter.h"
 #include "ImageRegion.h"
 #include "LookupResult.h"
 #include "Orientation.h"
 #include "SVGDocumentWrapper.h"
 #include "nsIDOMEventListener.h"
 #include "SurfaceCache.h"
+#include "nsDocument.h"
 
 // undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
 #undef GetCurrentTime
 
 namespace mozilla {
 
 using namespace dom;
 using namespace gfx;
@@ -1254,16 +1255,25 @@ void
 VectorImage::PropagateUseCounters(nsIDocument* aParentDocument)
 {
   nsIDocument* doc = mSVGDocumentWrapper->GetDocument();
   if (doc) {
     doc->PropagateUseCounters(aParentDocument);
   }
 }
 
+void
+VectorImage::ReportUseCounters()
+{
+  nsIDocument* doc = mSVGDocumentWrapper->GetDocument();
+  if (doc) {
+    static_cast<nsDocument*>(doc)->ReportUseCounters();
+  }
+}
+
 nsIntSize
 VectorImage::OptimalImageSizeForDest(const gfxSize& aDest,
                                      uint32_t aWhichFrame,
                                      GraphicsFilter aFilter,
                                      uint32_t aFlags)
 {
   MOZ_ASSERT(aDest.width >= 0 || ceil(aDest.width) <= INT32_MAX ||
              aDest.height >= 0 || ceil(aDest.height) <= INT32_MAX,
--- a/image/VectorImage.h
+++ b/image/VectorImage.h
@@ -63,16 +63,18 @@ public:
 
   // Callback for SVGParseCompleteListener.
   void OnSVGDocumentParsed();
 
   // Callbacks for SVGLoadEventListener.
   void OnSVGDocumentLoaded();
   void OnSVGDocumentError();
 
+  virtual void ReportUseCounters() override;
+
 protected:
   explicit VectorImage(ImageURL* aURI = nullptr);
   virtual ~VectorImage();
 
   virtual nsresult StartAnimation() override;
   virtual nsresult StopAnimation() override;
   virtual bool     ShouldAnimate() override;
 
--- a/layout/style/ImageLoader.cpp
+++ b/layout/style/ImageLoader.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/css/ImageLoader.h"
 #include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsError.h"
 #include "nsDisplayList.h"
 #include "FrameLayerBuilder.h"
 #include "nsSVGEffects.h"
 #include "imgIContainer.h"
+#include "Image.h"
 
 namespace mozilla {
 namespace css {
 
 void
 ImageLoader::DropDocumentReference()
 {
   // It's okay if GetPresContext returns null here (due to the presshell pointer
@@ -505,10 +506,27 @@ ImageLoader::UnblockOnload(imgIRequest* 
     return NS_OK;
   }
 
   mDocument->UnblockOnload(false);
 
   return NS_OK;
 }
 
+void
+ImageLoader::FlushUseCounters()
+{
+  for (auto iter = mImages.Iter(); !iter.Done(); iter.Next()) {
+    nsPtrHashKey<Image>* key = iter.Get();
+    ImageLoader::Image* image = key->GetKey();
+
+    imgIRequest* request = image->mRequests.GetWeak(mDocument);
+
+    nsCOMPtr<imgIContainer> container;
+    request->GetImage(getter_AddRefs(container));
+    if (container) {
+      static_cast<image::Image*>(container.get())->ReportUseCounters();
+    }
+  }
+}
+
 } // namespace css
 } // namespace mozilla
--- a/layout/style/ImageLoader.h
+++ b/layout/style/ImageLoader.h
@@ -65,16 +65,18 @@ public:
   // presshell pointer on the document has been cleared.
   void ClearFrames(nsPresContext* aPresContext);
 
   void LoadImage(nsIURI* aURI, nsIPrincipal* aPrincipal, nsIURI* aReferrer,
                  Image* aCSSValue);
 
   void DestroyRequest(imgIRequest* aRequest);
 
+  void FlushUseCounters();
+
 private:
   ~ImageLoader() {}
 
   // We need to be able to look up the frames associated with a request (for
   // delivering notifications) and the requests associated with a frame (when
   // the frame goes away). Thus we maintain hashtables going both ways.  These
   // should always be in sync.
 
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -193,16 +193,17 @@ LOCAL_INCLUDES += [
     '../base',
     '../generic',
     '../svg',
     '../xul',
     '/dom/base',
     '/dom/html',
     '/dom/xbl',
     '/dom/xul',
+    '/image',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
 
 RESOURCE_FILES += [
     'contenteditable.css',
     'designmode.css',
     'ImageDocument.css',