Bug 1027741 - Run decode complete notification handler for image documents on a script runner because they trigger invalidation and decode complete notifications are often dispatched during painting. r=smaug, a=lmandel
authorTimothy Nikkel <tnikkel@gmail.com>
Sun, 10 Aug 2014 13:01:40 -0500
changeset 208304 d4e47ec57f06
parent 208303 511ac00e4e6c
child 208305 cfec8a16880a
push id3813
push userryanvm@gmail.com
push date2014-08-14 13:03 +0000
treeherdermozilla-beta@cfec8a16880a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, lmandel
bugs1027741
milestone32.0
Bug 1027741 - Run decode complete notification handler for image documents on a script runner because they trigger invalidation and decode complete notifications are often dispatched during painting. r=smaug, a=lmandel
content/html/document/src/ImageDocument.cpp
content/html/document/src/ImageDocument.h
--- a/content/html/document/src/ImageDocument.cpp
+++ b/content/html/document/src/ImageDocument.cpp
@@ -454,49 +454,70 @@ NS_IMETHODIMP
 ImageDocument::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData)
 {
   if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
     nsCOMPtr<imgIContainer> image;
     aRequest->GetImage(getter_AddRefs(image));
     return OnStartContainer(aRequest, image);
   }
 
-  nsDOMTokenList* classList = mImageContent->AsElement()->ClassList();
-  mozilla::ErrorResult rv;
+  // Do these two off a script runner because decode complete notifications often
+  // come during painting and these will trigger invalidation.
   if (aType == imgINotificationObserver::DECODE_COMPLETE) {
-    if (mImageContent && !nsContentUtils::IsChildOfSameType(this)) {
-      // Update the background-color of the image only after the
-      // image has been decoded to prevent flashes of just the
-      // background-color.
-      classList->Add(NS_LITERAL_STRING("decoded"), rv);
-      NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
-    }
+    nsCOMPtr<nsIRunnable> runnable =
+      NS_NewRunnableMethod(this, &ImageDocument::AddDecodedClass);
+    nsContentUtils::AddScriptRunner(runnable);
   }
 
   if (aType == imgINotificationObserver::DISCARD) {
-    // mImageContent can be null if the document is already destroyed
-    if (mImageContent && !nsContentUtils::IsChildOfSameType(this)) {
-      // Remove any decoded-related styling when the image is unloaded.
-      classList->Remove(NS_LITERAL_STRING("decoded"), rv);
-      NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
-    }
+    nsCOMPtr<nsIRunnable> runnable =
+      NS_NewRunnableMethod(this, &ImageDocument::RemoveDecodedClass);
+    nsContentUtils::AddScriptRunner(runnable);
   }
 
   if (aType == imgINotificationObserver::LOAD_COMPLETE) {
     uint32_t reqStatus;
     aRequest->GetImageStatus(&reqStatus);
     nsresult status =
         reqStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK;
     return OnStopRequest(aRequest, status);
   }
 
   return NS_OK;
 }
 
 void
+ImageDocument::AddDecodedClass()
+{
+  if (!mImageContent || nsContentUtils::IsChildOfSameType(this)) {
+    return;
+  }
+
+  nsDOMTokenList* classList = mImageContent->AsElement()->ClassList();
+  mozilla::ErrorResult rv;
+  // Update the background-color of the image only after the
+  // image has been decoded to prevent flashes of just the
+  // background-color.
+  classList->Add(NS_LITERAL_STRING("decoded"), rv);
+}
+
+void
+ImageDocument::RemoveDecodedClass()
+{
+  if (!mImageContent || nsContentUtils::IsChildOfSameType(this)) {
+    return;
+  }
+
+  nsDOMTokenList* classList = mImageContent->AsElement()->ClassList();
+  mozilla::ErrorResult rv;
+  // Remove any decoded-related styling when the image is unloaded.
+  classList->Remove(NS_LITERAL_STRING("decoded"), rv);
+}
+
+void
 ImageDocument::SetModeClass(eModeClasses mode)
 {
   nsDOMTokenList* classList = mImageContent->AsElement()->ClassList();
   mozilla::ErrorResult rv;
 
   if (mode == eShrinkToFit) {
     classList->Add(NS_LITERAL_STRING("shrinkToFit"), rv);
   } else {
--- a/content/html/document/src/ImageDocument.h
+++ b/content/html/document/src/ImageDocument.h
@@ -47,16 +47,19 @@ public:
   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) MOZ_OVERRIDE;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ImageDocument, MediaDocument)
 
   friend class ImageListener;
 
   void DefaultCheckOverflowing() { CheckOverflowing(mResizeImageByDefault); }
 
+  void AddDecodedClass();
+  void RemoveDecodedClass();
+
   // WebIDL API
   virtual JSObject* WrapNode(JSContext* aCx)
     MOZ_OVERRIDE;
 
   bool ImageResizingEnabled() const
   {
     return true;
   }