Bug 1383682 - Part 3. Prevent imgRequestProxy from leaking the current state when validating. r=tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Wed, 07 Feb 2018 07:27:28 -0500
changeset 402772 30ee5a21a6a14cf3bb4e043b3129280a72e151ea
parent 402771 62497967f092c6c76778ddc1534f110d4583eeb9
child 402773 7d098669f8cb02be84451118e9c93bc0b9b3d461
push id33402
push useraciure@mozilla.com
push dateWed, 07 Feb 2018 22:06:27 +0000
treeherdermozilla-central@8cc2427a322c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel
bugs1383682
milestone60.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 1383682 - Part 3. Prevent imgRequestProxy from leaking the current state when validating. r=tnikkel There are two other means from which a caller can get the current state which originally ignored validation -- GetImageStatus and StartDecodingWithResult. These methods are used by layout in some circumstances to decide whether or not the image is ready to display. As observed in some web platform tests, in particular css/css-backgrounds-3/background-size-031.html, we may actually validate and purge the cache for images under test. The state given by the aforementioned methods was misleading, because validation changed it. Now they take into account validation, and do not imply any particular state while validation is in progress.
image/imgRequestProxy.cpp
--- a/image/imgRequestProxy.cpp
+++ b/image/imgRequestProxy.cpp
@@ -555,36 +555,42 @@ imgRequestProxy::CancelAndForgetObserver
   NullOutListener();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 imgRequestProxy::StartDecoding(uint32_t aFlags)
 {
-  // Flag this, so we know to transfer the request if our owner changes
-  mDecodeRequested = true;
+  // Flag this, so we know to request after validation if pending.
+  if (IsValidating()) {
+    mDecodeRequested = true;
+    return NS_OK;
+  }
 
   RefPtr<Image> image = GetImage();
   if (image) {
     return image->StartDecoding(aFlags);
   }
 
   if (GetOwner()) {
     GetOwner()->StartDecoding();
   }
 
   return NS_OK;
 }
 
 bool
 imgRequestProxy::StartDecodingWithResult(uint32_t aFlags)
 {
-  // Flag this, so we know to transfer the request if our owner changes
-  mDecodeRequested = true;
+  // Flag this, so we know to request after validation if pending.
+  if (IsValidating()) {
+    mDecodeRequested = true;
+    return false;
+  }
 
   RefPtr<Image> image = GetImage();
   if (image) {
     return image->StartDecodingWithResult(aFlags);
   }
 
   if (GetOwner()) {
     GetOwner()->StartDecoding();
@@ -731,18 +737,26 @@ imgRequestProxy::GetImage(imgIContainer*
   imageToReturn.swap(*aImage);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 imgRequestProxy::GetImageStatus(uint32_t* aStatus)
 {
-  RefPtr<ProgressTracker> progressTracker = GetProgressTracker();
-  *aStatus = progressTracker->GetImageStatus();
+  if (IsValidating()) {
+    // We are currently validating the image, and so our status could revert if
+    // we discard the cache. We should also be deferring notifications, such
+    // that the caller will be notified when validation completes. Rather than
+    // risk misleading the caller, return nothing.
+    *aStatus = imgIRequest::STATUS_NONE;
+  } else {
+    RefPtr<ProgressTracker> progressTracker = GetProgressTracker();
+    *aStatus = progressTracker->GetImageStatus();
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 imgRequestProxy::GetImageErrorCode(nsresult* aStatus)
 {
   if (!GetOwner()) {