Bug 1457532: Narrow ImageLoader::OnLoadComplete to only unblock onload in response to an error status on the image request. draft
authorBrad Werth <bwerth@mozilla.com>
Fri, 27 Apr 2018 12:00:35 -0700
changeset 789176 d9a89e0a73e702fe880284275428e1e332571ef0
parent 789020 d2d518b1f8730eb61554df7179ef9a2aeed4d843
push id108211
push userbwerth@mozilla.com
push dateFri, 27 Apr 2018 19:03:22 +0000
bugs1457532
milestone61.0a1
Bug 1457532: Narrow ImageLoader::OnLoadComplete to only unblock onload in response to an error status on the image request. MozReview-Commit-ID: 929PTrT9iP1
layout/style/ImageLoader.cpp
layout/style/ImageLoader.h
--- a/layout/style/ImageLoader.cpp
+++ b/layout/style/ImageLoader.cpp
@@ -486,20 +486,16 @@ ImageLoader::RequestReflowIfNeeded(Frame
       RequestReflowOnFrame(&fwf, aRequest);
     }
   }
 }
 
 void
 ImageLoader::RequestReflowOnFrame(FrameWithFlags* aFwf, imgIRequest* aRequest)
 {
-  // Set the flag indicating that we've requested reflow. This flag will never
-  // be unset.
-  aFwf->mFlags |= REQUEST_HAS_REQUESTED_REFLOW;
-
   nsIFrame* frame = aFwf->mFrame;
 
   // Actually request the reflow.
   nsIFrame* parent = frame->GetInFlowParent();
   parent->PresShell()->FrameNeedsReflow(parent, nsIPresShell::eStyleChange,
                                         NS_FRAME_IS_DIRTY);
 
   // We'll respond to the reflow events by unblocking onload, regardless
@@ -662,29 +658,29 @@ ImageLoader::OnLoadComplete(imgIRequest*
     return NS_OK;
   }
 
   FrameSet* frameSet = mRequestToFrameMap.Get(aRequest);
   if (!frameSet) {
     return NS_OK;
   }
 
-  // This may be called for a request that never sent a complete frame.
-  // This is what happens in a CORS mode violation, and may happen during
-  // other network events. We check for any frames that have blocked
-  // onload but haven't requested reflow. In such a case, we unblock
-  // onload here, since onFrameComplete will not be called for this request.
-  FrameFlags flagsToCheck(REQUEST_HAS_BLOCKED_ONLOAD |
-                          REQUEST_HAS_REQUESTED_REFLOW);
-  for (FrameWithFlags& fwf : *frameSet) {
-    if ((fwf.mFlags & flagsToCheck) == REQUEST_HAS_BLOCKED_ONLOAD) {
-      // We've blocked onload but haven't requested reflow. Unblock onload
-      // and clear the flag.
-      mDocument->UnblockOnload(false);
-      fwf.mFlags &= ~REQUEST_HAS_BLOCKED_ONLOAD;
+  // Check if aRequest has an error state. If it does, we need to unblock
+  // Document onload for all the frames associated with this request that
+  // have blocked onload. This is what happens in a CORS mode violation, and
+  // may happen during other network events.
+  uint32_t status = 0;
+  if(NS_SUCCEEDED(aRequest->GetImageStatus(&status)) &&
+     status & imgIRequest::STATUS_ERROR) {
+    for (FrameWithFlags& fwf : *frameSet) {
+      if (fwf.mFlags & REQUEST_HAS_BLOCKED_ONLOAD) {
+        // We've blocked onload. Unblock onload and clear the flag.
+        mDocument->UnblockOnload(false);
+        fwf.mFlags &= ~REQUEST_HAS_BLOCKED_ONLOAD;
+      }
     }
   }
 
   return NS_OK;
 }
 
 void
 ImageLoader::FlushUseCounters()
--- a/layout/style/ImageLoader.h
+++ b/layout/style/ImageLoader.h
@@ -35,18 +35,17 @@ struct ImageValue;
 class ImageLoader final : public imgINotificationObserver
 {
 public:
   // We also associate flags alongside frames in the request-to-frames hashmap.
   // These are used for special handling of events for requests.
   typedef uint32_t FrameFlags;
   enum {
     REQUEST_REQUIRES_REFLOW      = 1u << 0,
-    REQUEST_HAS_REQUESTED_REFLOW = 1u << 1,
-    REQUEST_HAS_BLOCKED_ONLOAD   = 1u << 2
+    REQUEST_HAS_BLOCKED_ONLOAD   = 1u << 1,
   };
 
   typedef mozilla::css::ImageValue Image;
 
   explicit ImageLoader(nsIDocument* aDocument)
   : mDocument(aDocument),
     mInClone(false)
   {