summaryrefslogtreecommitdiff
path: root/dom/base/nsImageLoadingContent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/nsImageLoadingContent.cpp')
-rw-r--r--dom/base/nsImageLoadingContent.cpp101
1 files changed, 51 insertions, 50 deletions
diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp
index 0c6c37b443..4aad55941c 100644
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -44,6 +44,7 @@
#include "mozAutoDocUpdate.h"
#include "mozilla/AsyncEventDispatcher.h"
+#include "mozilla/AutoRestore.h"
#include "mozilla/EventStates.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ImageTracker.h"
@@ -94,7 +95,8 @@ nsImageLoadingContent::nsImageLoadingContent()
mNewRequestsWillNeedAnimationReset(false),
mStateChangerDepth(0),
mCurrentRequestRegistered(false),
- mPendingRequestRegistered(false)
+ mPendingRequestRegistered(false),
+ mIsStartingImageLoad(false)
{
if (!nsContentUtils::GetImgLoaderForChannel(nullptr, nullptr)) {
mLoadingEnabled = false;
@@ -785,6 +787,11 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
nsIDocument* aDocument,
nsLoadFlags aLoadFlags)
{
+ MOZ_ASSERT(!mIsStartingImageLoad, "some evil code is reentering LoadImage.");
+ if (mIsStartingImageLoad) {
+ return NS_OK;
+ }
+
// Pending load/error events need to be canceled in some situations. This
// is not documented in the spec, but can cause site compat problems if not
// done. See bug 1309461 and https://github.com/whatwg/html/issues/1872.
@@ -814,6 +821,21 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
}
}
+ AutoRestore<bool> guard(mIsStartingImageLoad);
+ mIsStartingImageLoad = true;
+
+ // Data documents, or documents from DOMParser shouldn't perform image loading.
+ if (aDocument->IsLoadedAsData()) {
+ // This is the only codepath on which we can reach SetBlockedRequest while
+ // our pending request exists. Just clear it out here if we do have one.
+ ClearPendingRequest(NS_BINDING_ABORTED,
+ Some(OnNonvisible::DISCARD_IMAGES));
+ SetBlockedRequest(nsIContentPolicy::REJECT_REQUEST);
+ FireEvent(NS_LITERAL_STRING("error"));
+ FireEvent(NS_LITERAL_STRING("loadend"));
+ return NS_OK;
+ }
+
// URI equality check.
//
// We skip the equality check if our current image was blocked, since in that
@@ -844,23 +866,8 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
"Principal mismatch?");
#endif
- // Are we blocked?
- int16_t cpDecision = nsIContentPolicy::REJECT_REQUEST;
nsContentPolicyType policyType = PolicyTypeForLoad(aImageLoadType);
- nsContentUtils::CanLoadImage(aNewURI,
- static_cast<nsIImageLoadingContent*>(this),
- aDocument,
- aDocument->NodePrincipal(),
- &cpDecision,
- policyType);
- if (!NS_CP_ACCEPTED(cpDecision)) {
- FireEvent(NS_LITERAL_STRING("error"));
- FireEvent(NS_LITERAL_STRING("loadend"));
- SetBlockedRequest(aNewURI, cpDecision);
- return NS_OK;
- }
-
nsLoadFlags loadFlags = aLoadFlags;
int32_t corsmode = GetCORSMode();
if (corsmode == CORS_ANONYMOUS) {
@@ -878,7 +885,6 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
referrerPolicy = imgReferrerPolicy;
}
- // Not blocked. Do the load.
RefPtr<imgRequestProxy>& req = PrepareNextRequest(aImageLoadType);
nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
@@ -932,7 +938,6 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
FireEvent(NS_LITERAL_STRING("error"));
FireEvent(NS_LITERAL_STRING("loadend"));
- return NS_OK;
}
return NS_OK;
@@ -1212,46 +1217,42 @@ nsImageLoadingContent::PrepareNextRequest(ImageLoadType aImageLoadType)
mMostRecentRequestChange = now;
}
- // If we don't have a usable current request, get rid of any half-baked
- // request that might be sitting there and make this one current.
- if (!HaveSize(mCurrentRequest))
- return PrepareCurrentRequest(aImageLoadType);
- // Otherwise, make it pending.
- return PreparePendingRequest(aImageLoadType);
+ // We only want to cancel the existing current request if size is not
+ // available. bz says the web depends on this behavior.
+ // Otherwise, we get rid of any half-baked request that might be sitting there
+ // and make this one current.
+ // TODO: Bug 583491
+ // Investigate/Cleanup NS_ERROR_IMAGE_SRC_CHANGED use in nsImageFrame.cpp
+ return HaveSize(mCurrentRequest) ?
+ PreparePendingRequest(aImageLoadType) :
+ PrepareCurrentRequest(aImageLoadType);
}
-void
-nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, int16_t aContentDecision)
+nsresult
+nsImageLoadingContent::SetBlockedRequest(int16_t aContentDecision)
{
+ // If this is not calling from LoadImage, for example, from ServiceWorker,
+ // bail out.
+ if (!mIsStartingImageLoad) {
+ return NS_OK;
+ }
+
// Sanity
MOZ_ASSERT(!NS_CP_ACCEPTED(aContentDecision), "Blocked but not?");
- // We do some slightly illogical stuff here to maintain consistency with
- // old behavior that people probably depend on. Even in the case where the
- // new image is blocked, the old one should really be canceled with the
- // reason "image source changed". However, apparently there's some abuse
- // over in nsImageFrame where the displaying of the "broken" icon for the
- // next image depends on the cancel reason of the previous image. ugh.
- // XXX(seth): So shouldn't we fix nsImageFrame?!
- ClearPendingRequest(NS_ERROR_IMAGE_BLOCKED,
- Some(OnNonvisible::DISCARD_IMAGES));
-
- // For the blocked case, we only want to cancel the existing current request
- // if size is not available. bz says the web depends on this behavior.
- if (!HaveSize(mCurrentRequest)) {
+ // We should never have a pending request after we got blocked.
+ MOZ_ASSERT(!mPendingRequest, "mPendingRequest should be null.");
+ if (HaveSize(mCurrentRequest)) {
+ // PreparePendingRequest set mPendingRequestFlags, now since we've decided
+ // to block it, we reset it back to 0.
+ mPendingRequestFlags = 0;
+ } else {
mImageBlockingStatus = aContentDecision;
- uint32_t keepFlags = mCurrentRequestFlags & REQUEST_IS_IMAGESET;
- ClearCurrentRequest(NS_ERROR_IMAGE_BLOCKED,
- Some(OnNonvisible::DISCARD_IMAGES));
-
- // We still want to remember what URI we were and if it was an imageset,
- // despite not having an actual request. These are both cleared as part of
- // ClearCurrentRequest() before a new request is started.
- mCurrentURI = aURI;
- mCurrentRequestFlags = keepFlags;
}
+
+ return NS_OK;
}
RefPtr<imgRequestProxy>&
@@ -1262,7 +1263,7 @@ nsImageLoadingContent::PrepareCurrentRequest(ImageLoadType aImageLoadType)
mImageBlockingStatus = nsIContentPolicy::ACCEPT;
// Get rid of anything that was there previously.
- ClearCurrentRequest(NS_ERROR_IMAGE_SRC_CHANGED,
+ ClearCurrentRequest(NS_BINDING_ABORTED,
Some(OnNonvisible::DISCARD_IMAGES));
if (mNewRequestsWillNeedAnimationReset) {
@@ -1281,7 +1282,7 @@ RefPtr<imgRequestProxy>&
nsImageLoadingContent::PreparePendingRequest(ImageLoadType aImageLoadType)
{
// Get rid of anything that was there previously.
- ClearPendingRequest(NS_ERROR_IMAGE_SRC_CHANGED,
+ ClearPendingRequest(NS_BINDING_ABORTED,
Some(OnNonvisible::DISCARD_IMAGES));
if (mNewRequestsWillNeedAnimationReset) {