diff --git a/devtools/client/webconsole/test/node/fixtures/stubs/networkEvent.js b/devtools/client/webconsole/test/node/fixtures/stubs/networkEvent.js index d5af9db00df78..b599fee7c6c0b 100644 --- a/devtools/client/webconsole/test/node/fixtures/stubs/networkEvent.js +++ b/devtools/client/webconsole/test/node/fixtures/stubs/networkEvent.js @@ -29,14 +29,7 @@ rawPackets.set(`GET request`, { "cause": { "loadingDocumentUri": "https://example.com/browser/devtools/client/webconsole/test/browser/stub-generators/test-network-event.html", "type": "img", - "stacktraceAvailable": true, - "lastFrame": { - "filename": "https://example.com/browser/devtools/client/webconsole/test/browser/stub-generators/test-network-event.html", - "lineNumber": 3, - "columnNumber": 1, - "functionName": "triggerPacket", - "asyncCause": null - } + "stacktraceAvailable": false }, "httpVersion": "HTTP/1.1", "status": "404", @@ -68,14 +61,7 @@ rawPackets.set(`GET request update`, { "cause": { "loadingDocumentUri": "https://example.com/browser/devtools/client/webconsole/test/browser/stub-generators/test-network-event.html", "type": "img", - "stacktraceAvailable": true, - "lastFrame": { - "filename": "https://example.com/browser/devtools/client/webconsole/test/browser/stub-generators/test-network-event.html", - "lineNumber": 3, - "columnNumber": 1, - "functionName": "triggerPacket", - "asyncCause": null - } + "stacktraceAvailable": false }, "httpVersion": "HTTP/1.1", "status": "404", diff --git a/devtools/shared/commands/resource/tests/browser_resources_network_events_parent_process.js b/devtools/shared/commands/resource/tests/browser_resources_network_events_parent_process.js index dc92354f3635f..ad03ac015828c 100644 --- a/devtools/shared/commands/resource/tests/browser_resources_network_events_parent_process.js +++ b/devtools/shared/commands/resource/tests/browser_resources_network_events_parent_process.js @@ -21,8 +21,8 @@ const createParentProcessRequests = async () => { const EXPECTED_METHOD_NAME = "createParentProcessRequests"; const EXPECTED_REQUEST_LINE_1 = 12; const EXPECTED_REQUEST_COL_1 = 9; -const EXPECTED_REQUEST_LINE_2 = 17; -const EXPECTED_REQUEST_COL_2 = 3; +// const EXPECTED_REQUEST_LINE_2 = 17; +// const EXPECTED_REQUEST_COL_2 = 3; // Test the ResourceCommand API around NETWORK_EVENT for the parent process @@ -133,13 +133,20 @@ add_task(async function testParentProcessRequests() { ok(!firstImageRequest.fromCache, "The first image request isn't cached"); ok(firstImageRequest.chromeContext, "The first image request is privileged"); - const firstImageStacktrace = receivedStacktraces[1].lastFrame; is(receivedStacktraces[1].resourceId, firstImageRequest.stacktraceResourceId); + const firstImageStacktrace = receivedStacktraces[1].lastFrame; + // TODO(bug 1911435). + todo( + !!firstImageStacktrace, + "After bug 1076583, image load is async and we can't get a stack trace" + ); + /* is(firstImageStacktrace.filename, gTestPath); is(firstImageStacktrace.lineNumber, EXPECTED_REQUEST_LINE_2); is(firstImageStacktrace.columnNumber, EXPECTED_REQUEST_COL_2); is(firstImageStacktrace.functionName, EXPECTED_METHOD_NAME); is(firstImageStacktrace.asyncCause, null); + */ info("Assert the second image request"); const secondImageRequest = receivedNetworkEvents[2]; diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp index 863061f452b12..9fd6488850064 100644 --- a/dom/base/DOMIntersectionObserver.cpp +++ b/dom/base/DOMIntersectionObserver.cpp @@ -149,7 +149,7 @@ static void LazyLoadCallback( Element* target = entry->Target(); if (entry->IsIntersecting()) { if (auto* image = HTMLImageElement::FromNode(target)) { - image->StopLazyLoading(HTMLImageElement::StartLoading::Yes); + image->StopLazyLoading(); } else if (auto* iframe = HTMLIFrameElement::FromNode(target)) { iframe->StopLazyLoading(); } else { diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp index fa1798ce3532e..c12a0e343b7c5 100644 --- a/dom/base/nsImageLoadingContent.cpp +++ b/dom/base/nsImageLoadingContent.cpp @@ -105,7 +105,6 @@ nsImageLoadingContent::nsImageLoadingContent() mRequestGeneration(0), mLoadingEnabled(true), mLoading(false), - mNewRequestsWillNeedAnimationReset(false), mUseUrgentStartForChannel(false), mLazyLoading(false), mStateChangerDepth(0), @@ -971,7 +970,6 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel, if (NS_SUCCEEDED(rv)) { CloneScriptedRequests(req); TrackImage(req); - ResetAnimationIfNeeded(); return NS_OK; } @@ -1167,7 +1165,6 @@ nsresult nsImageLoadingContent::LoadImage(nsIURI* aNewURI, bool aForce, CloneScriptedRequests(req); TrackImage(req); - ResetAnimationIfNeeded(); // Handle cases when we just ended up with a request but it's already done. // In that situation we have to synchronously switch that request to being @@ -1483,10 +1480,6 @@ RefPtr& nsImageLoadingContent::PrepareCurrentRequest( // Get rid of anything that was there previously. ClearCurrentRequest(NS_BINDING_ABORTED, Some(OnNonvisible::DiscardImages)); - if (mNewRequestsWillNeedAnimationReset) { - mCurrentRequestFlags |= REQUEST_NEEDS_ANIMATION_RESET; - } - if (aImageLoadType == eImageLoadType_Imageset) { mCurrentRequestFlags |= REQUEST_IS_IMAGESET; } @@ -1500,10 +1493,6 @@ RefPtr& nsImageLoadingContent::PreparePendingRequest( // Get rid of anything that was there previously. ClearPendingRequest(NS_BINDING_ABORTED, Some(OnNonvisible::DiscardImages)); - if (mNewRequestsWillNeedAnimationReset) { - mPendingRequestFlags |= REQUEST_NEEDS_ANIMATION_RESET; - } - if (aImageLoadType == eImageLoadType_Imageset) { mPendingRequestFlags |= REQUEST_IS_IMAGESET; } @@ -1562,7 +1551,6 @@ void nsImageLoadingContent::MakePendingRequestCurrent() { mPendingRequestFlags = 0; mCurrentRequestRegistered = mPendingRequestRegistered; mPendingRequestRegistered = false; - ResetAnimationIfNeeded(); } void nsImageLoadingContent::ClearCurrentRequest( @@ -1606,16 +1594,6 @@ void nsImageLoadingContent::ClearPendingRequest( mPendingRequestFlags = 0; } -void nsImageLoadingContent::ResetAnimationIfNeeded() { - if (mCurrentRequest && - (mCurrentRequestFlags & REQUEST_NEEDS_ANIMATION_RESET)) { - nsCOMPtr container; - mCurrentRequest->GetImage(getter_AddRefs(container)); - if (container) container->ResetAnimation(); - mCurrentRequestFlags &= ~REQUEST_NEEDS_ANIMATION_RESET; - } -} - bool nsImageLoadingContent::HaveSize(imgIRequest* aImage) { // Handle the null case if (!aImage) return false; diff --git a/dom/base/nsImageLoadingContent.h b/dom/base/nsImageLoadingContent.h index 2b6dac53fb91f..a84836d3561bf 100644 --- a/dom/base/nsImageLoadingContent.h +++ b/dom/base/nsImageLoadingContent.h @@ -424,13 +424,6 @@ class nsImageLoadingContent : public nsIImageLoadingContent { nsresult aReason, const Maybe& aNonvisibleAction = Nothing()); - /** - * Reset animation of the current request if - * |mNewRequestsWillNeedAnimationReset| was true when the request was - * prepared. - */ - void ResetAnimationIfNeeded(); - /** * Static helper method to tell us if we have the size of a request. The * image may be null. @@ -467,13 +460,11 @@ class nsImageLoadingContent : public nsIImageLoadingContent { uint8_t mPendingRequestFlags = 0; enum { - // Set if the request needs ResetAnimation called on it. - REQUEST_NEEDS_ANIMATION_RESET = 1 << 0, // Set if the request is currently tracked with the document. - REQUEST_IS_TRACKED = 1 << 1, + REQUEST_IS_TRACKED = 1 << 0, // Set if this is an imageset request, such as from or // - REQUEST_IS_IMAGESET = 1 << 2, + REQUEST_IS_IMAGESET = 1 << 1, }; // If the image was blocked or if there was an error loading, it's nice to @@ -565,16 +556,6 @@ class nsImageLoadingContent : public nsIImageLoadingContent { */ bool mLoading : 1; - /** - * A hack to get animations to reset, see bug 594771. On requests - * that originate from setting .src, we mark them for needing their animation - * reset when they are ready. mNewRequestsWillNeedAnimationReset is set to - * true while preparing such requests (as a hack around needing to change an - * interface), and the other two booleans store which of the current - * and pending requests are of the sort that need their animation restarted. - */ - bool mNewRequestsWillNeedAnimationReset : 1; - /** * Flag to indicate whether the channel should be mark as urgent-start. * It should be set in *Element and passed to nsContentUtils::LoadImage. diff --git a/dom/base/test/browser_blocking_image.js b/dom/base/test/browser_blocking_image.js index 5749937f07a8d..5dec9a586a928 100644 --- a/dom/base/test/browser_blocking_image.js +++ b/dom/base/test/browser_blocking_image.js @@ -158,8 +158,6 @@ add_task(async function block_pending_request_test() { let img = content.document.createElement("img"); img.src = "https://example.com/tests/image/test/mochitest/shaver.png"; - - let req = img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST); img.addObserver(observer); content.document.body.appendChild(img); @@ -169,6 +167,7 @@ add_task(async function block_pending_request_test() { info("Size Available now!"); img.removeObserver(observer); + let req = img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST); // Now we change to load from http:// site, which will be blocked. img.src = "http://example.com/tests/image/test/mochitest/shaver.png"; diff --git a/dom/html/HTMLImageElement.cpp b/dom/html/HTMLImageElement.cpp index 597d7f4b22bbe..4024846211427 100644 --- a/dom/html/HTMLImageElement.cpp +++ b/dom/html/HTMLImageElement.cpp @@ -77,7 +77,7 @@ namespace mozilla::dom { // Calls LoadSelectedImage on host element unless it has been superseded or // canceled -- this is the synchronous section of "update the image data". -// https://html.spec.whatwg.org/multipage/embedded-content.html#update-the-image-data +// https://html.spec.whatwg.org/#update-the-image-data class ImageLoadTask final : public MicroTaskRunnable { public: ImageLoadTask(HTMLImageElement* aElement, bool aAlwaysLoad, @@ -93,7 +93,7 @@ class ImageLoadTask final : public MicroTaskRunnable { if (mElement->mPendingImageLoadTask == this) { mElement->mPendingImageLoadTask = nullptr; mElement->mUseUrgentStartForChannel = mUseUrgentStartForChannel; - mElement->LoadSelectedImage(true, true, mAlwaysLoad); + mElement->LoadSelectedImage(mAlwaysLoad); } mDocument->UnblockOnload(false); } @@ -165,12 +165,11 @@ bool HTMLImageElement::Draggable() const { bool HTMLImageElement::Complete() { // It is still not clear what value should img.complete return in various // cases, see https://github.com/whatwg/html/issues/4884 - if (!HasAttr(nsGkAtoms::srcset) && !HasNonEmptyAttr(nsGkAtoms::src)) { return true; } - if (!mCurrentRequest || mPendingRequest) { + if (!mCurrentRequest || mPendingRequest || mPendingImageLoadTask) { return false; } @@ -321,32 +320,24 @@ void HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, } bool forceReload = false; - if (aName == nsGkAtoms::loading && !mLoading) { if (aValue && Loading(aValue->GetEnumValue()) == Loading::Lazy) { SetLazyLoading(); } else if (aOldValue && Loading(aOldValue->GetEnumValue()) == Loading::Lazy) { - StopLazyLoading(StartLoading::Yes); + StopLazyLoading(StartLoad(aNotify)); } } else if (aName == nsGkAtoms::src && !aValue) { + // AfterMaybeChangeAttr handles setting src since it needs to catch + // img.src = img.src, so we only need to handle the unset case // NOTE: regular src value changes are handled in AfterMaybeChangeAttr, so // this only needs to handle unsetting the src attribute. // Mark channel as urgent-start before load image if the image load is - // initaiated by a user interaction. - mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput(); - - // AfterMaybeChangeAttr handles setting src since it needs to catch - // img.src = img.src, so we only need to handle the unset case - if (InResponsiveMode()) { - if (mResponsiveSelector && mResponsiveSelector->Content() == this) { - mResponsiveSelector->SetDefaultSource(VoidString()); - } - UpdateSourceSyncAndQueueImageTask(true); - } else { - // Bug 1076583 - We still behave synchronously in the non-responsive case - CancelImageRequests(aNotify); + // initiated by a user interaction. + if (mResponsiveSelector && mResponsiveSelector->Content() == this) { + mResponsiveSelector->SetDefaultSource(VoidString()); } + forceReload = true; } else if (aName == nsGkAtoms::srcset) { // Mark channel as urgent-start before load image if the image load is // initaiated by a user interaction. @@ -368,37 +359,20 @@ void HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, ImageDecodingType::Sync); } else if (aName == nsGkAtoms::referrerpolicy) { ReferrerPolicy referrerPolicy = GetReferrerPolicyAsEnum(); - // FIXME(emilio): Why only when not in responsive mode? Also see below for - // aNotify. - forceReload = aNotify && !InResponsiveMode() && - referrerPolicy != ReferrerPolicy::_empty && + forceReload = referrerPolicy != ReferrerPolicy::_empty && referrerPolicy != ReferrerPolicyFromAttr(aOldValue); } else if (aName == nsGkAtoms::crossorigin) { - // FIXME(emilio): The aNotify bit seems a bit suspicious, but it is useful - // to avoid extra sync loads, specially in non-responsive mode. Ideally we - // can unify the responsive and non-responsive code paths (bug 1076583), and - // simplify this a bit. - forceReload = aNotify && GetCORSMode() != AttrValueToCORSMode(aOldValue); + forceReload = GetCORSMode() != AttrValueToCORSMode(aOldValue); } - if (forceReload) { - // Because we load image synchronously in non-responsive-mode, we need to do - // reload after the attribute has been set if the reload is triggered by - // cross origin / referrer policy changing. - // - // Mark channel as urgent-start before load image if the image load is - // initiated by a user interaction. + // NOTE(emilio): When not notifying, we come from the parser or some other + // internal caller, in which cases we can skip the load since we are about to + // get bound to a tree. + if (forceReload && aNotify) { + // Per spec, full selection runs when this changes, even though it doesn't + // directly affect the source selection. mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput(); - if (InResponsiveMode()) { - // Per spec, full selection runs when this changes, even though - // it doesn't directly affect the source selection - UpdateSourceSyncAndQueueImageTask(true); - } else if (ShouldLoadImage()) { - // Bug 1076583 - We still use the older synchronous algorithm in - // non-responsive mode. Force a new load of the image with the - // new cross origin policy - ForceReload(aNotify, IgnoreErrors()); - } + UpdateSourceSyncAndQueueImageTask(true); } return nsGenericHTMLElement::AfterSetAttr( @@ -427,47 +401,19 @@ void HTMLImageElement::AfterMaybeChangeAttr( // being set to its existing value, which is normally optimized away as a // no-op. // - // If we are in responsive mode, we drop the forced reload behavior, - // but still trigger a image load task for img.src = img.src per - // spec. + // If we are in responsive mode, we drop the forced reload behavior, but still + // trigger a image load task for img.src = img.src per spec. // // Both cases handle unsetting src in AfterSetAttr - // Mark channel as urgent-start before load image if the image load is - // initaiated by a user interaction. - mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput(); - mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal( this, aValue.String(), aMaybeScriptedPrincipal); - if (InResponsiveMode()) { - if (mResponsiveSelector && mResponsiveSelector->Content() == this) { - mResponsiveSelector->SetDefaultSource(mSrcURI, mSrcTriggeringPrincipal); - } + if (mResponsiveSelector && mResponsiveSelector->Content() == this) { + mResponsiveSelector->SetDefaultSource(mSrcURI, mSrcTriggeringPrincipal); + } + if (aNotify) { + mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput(); UpdateSourceSyncAndQueueImageTask(true); - } else if (aNotify && ShouldLoadImage()) { - // If aNotify is false, we are coming from the parser or some such place; - // we'll get bound after all the attributes have been set, so we'll do the - // sync image load from BindToTree. Skip the LoadImage call in that case. - - // Note that this sync behavior is partially removed from the spec, bug - // 1076583 - - // A hack to get animations to reset. See bug 594771. - mNewRequestsWillNeedAnimationReset = true; - - // Force image loading here, so that we'll try to load the image from - // network if it's set to be not cacheable. - // Potentially, false could be passed here rather than aNotify since - // UpdateState will be called by SetAttrAndNotify, but there are two - // obstacles to this: 1) LoadImage will end up calling - // UpdateState(aNotify), and we do not want it to call UpdateState(false) - // when aNotify is true, and 2) When this function is called by - // OnAttrSetButNotChanged, SetAttrAndNotify will not subsequently call - // UpdateState. - LoadSelectedImage(/* aForce = */ true, aNotify, - /* aAlwaysLoad = */ true); - - mNewRequestsWillNeedAnimationReset = false; } } @@ -513,59 +459,31 @@ bool HTMLImageElement::IsHTMLFocusable(IsFocusableFlags aFlags, } nsresult HTMLImageElement::BindToTree(BindContext& aContext, nsINode& aParent) { - nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent); - NS_ENSURE_SUCCESS(rv, rv); + MOZ_TRY(nsGenericHTMLElement::BindToTree(aContext, aParent)); nsImageLoadingContent::BindToTree(aContext, aParent); UpdateFormOwner(); - if (HaveSrcsetOrInPicture()) { - if (IsInComposedDoc() && !mInDocResponsiveContent) { - aContext.OwnerDoc().AddResponsiveContent(this); - mInDocResponsiveContent = true; - } - - // Mark channel as urgent-start before load image if the image load is - // initaiated by a user interaction. - mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput(); - - // Run selection algorithm when an img element is inserted into a document - // in order to react to changes in the environment. See note of - // https://html.spec.whatwg.org/multipage/embedded-content.html#img-environment-changes - // - // We also do this in PictureSourceAdded() if it is in , so here - // we only need to do if its parent is not , even if there is no - // . - if (!IsInPicture()) { - UpdateSourceSyncAndQueueImageTask(false); - } - } else if (!InResponsiveMode() && HasAttr(nsGkAtoms::src)) { - // We skip loading when our attributes were set from parser land, - // so trigger a aForce=false load now to check if things changed. - // This isn't necessary for responsive mode, since creating the - // image load task is asynchronous we don't need to take special - // care to avoid doing so when being filled by the parser. - - // Mark channel as urgent-start before load image if the image load is - // initaiated by a user interaction. - mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput(); - - // We still act synchronously for the non-responsive case (Bug - // 1076583), but still need to delay if it is unsafe to run - // script. - - // If loading is temporarily disabled, don't even launch MaybeLoadImage. - // Otherwise MaybeLoadImage may run later when someone has reenabled - // loading. - if (LoadingEnabled() && ShouldLoadImage()) { - nsContentUtils::AddScriptRunner( - NewRunnableMethod("dom::HTMLImageElement::MaybeLoadImage", this, - &HTMLImageElement::MaybeLoadImage, false)); - } + const bool srcsetOrPicture = HaveSrcsetOrInPicture(); + if (srcsetOrPicture && aContext.InComposedDoc() && !mInDocResponsiveContent) { + aContext.OwnerDoc().AddResponsiveContent(this); + mInDocResponsiveContent = true; } - return rv; + // Mark channel as urgent-start before load image if the image load is + // initiated by a user interaction. + mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput(); + // Run selection algorithm when an img element is inserted into a document + // in order to react to changes in the environment. See note of + // https://html.spec.whatwg.org/#img-environment-changes + // + // We skip loading when our attributes were set from parser land (see the + // aNotify checks in the various attribute mutation functions), so trigger a + // aAlwaysLoad=false load now to check if things changed. + UpdateSourceSyncAndQueueImageTask(false); + + return NS_OK; } void HTMLImageElement::UnbindFromTree(UnbindContext& aContext) { @@ -611,21 +529,6 @@ void HTMLImageElement::UpdateFormOwner() { } } -void HTMLImageElement::MaybeLoadImage(bool aAlwaysForceLoad) { - // Our base URI may have changed, or we may have had responsive parameters - // change while not bound to the tree. However, at this moment, we should have - // updated the responsive source in other places, so we don't have to re-parse - // src/srcset here. Just need to LoadImage. - - // Note, check LoadingEnabled() after LoadImage call. - - LoadSelectedImage(aAlwaysForceLoad, /* aNotify */ true, aAlwaysForceLoad); - - if (!LoadingEnabled()) { - CancelImageRequests(true); - } -} - void HTMLImageElement::NodeInfoChanged(Document* aOldDoc) { nsGenericHTMLElement::NodeInfoChanged(aOldDoc); @@ -644,19 +547,12 @@ void HTMLImageElement::NodeInfoChanged(Document* aOldDoc) { SetLazyLoading(); } - // Run selection algorithm synchronously when an img element's adopting steps - // are run, in order to react to changes in the environment, per spec, - // https://html.spec.whatwg.org/multipage/images.html#reacting-to-dom-mutations, - // and - // https://html.spec.whatwg.org/multipage/images.html#reacting-to-environment-changes. - if (InResponsiveMode()) { - UpdateResponsiveSource(); - } - - // Force reload image if adoption steps are run. - // If loading is temporarily disabled, don't even launch script runner. - // Otherwise script runner may run later when someone has reenabled loading. - StartLoadingIfNeeded(); + // Run selection algorithm synchronously and reload when an img element's + // adopting steps are run, in order to react to changes in the environment, + // per spec, + // https://html.spec.whatwg.org/#reacting-to-dom-mutations, and + // https://html.spec.whatwg.org/#reacting-to-environment-changes. + UpdateSourceSyncAndQueueImageTask(true); } // static @@ -727,26 +623,13 @@ nsIntSize HTMLImageElement::NaturalSize() { } nsresult HTMLImageElement::CopyInnerTo(HTMLImageElement* aDest) { - nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest); - if (NS_FAILED(rv)) { - return rv; - } + MOZ_TRY(nsGenericHTMLElement::CopyInnerTo(aDest)); // In SetAttr (called from nsGenericHTMLElement::CopyInnerTo), aDest skipped // doing the image load because we passed in false for aNotify. But we // really do want it to do the load, so set it up to happen once the cloning // reaches a stable state. - if (!aDest->InResponsiveMode() && aDest->HasAttr(nsGkAtoms::src) && - aDest->ShouldLoadImage()) { - // Mark channel as urgent-start before load image if the image load is - // initaiated by a user interaction. - mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput(); - - nsContentUtils::AddScriptRunner( - NewRunnableMethod("dom::HTMLImageElement::MaybeLoadImage", aDest, - &HTMLImageElement::MaybeLoadImage, false)); - } - + aDest->UpdateSourceSyncAndQueueImageTask(false); return NS_OK; } @@ -799,6 +682,7 @@ void HTMLImageElement::ClearForm(bool aRemoveFromForm) { mForm = nullptr; } +// Roughly corresponds to https://html.spec.whatwg.org/#update-the-image-data void HTMLImageElement::UpdateSourceSyncAndQueueImageTask( bool aAlwaysLoad, const HTMLSourceElement* aSkippedSource) { // Per spec, when updating the image data or reacting to environment @@ -809,45 +693,77 @@ void HTMLImageElement::UpdateSourceSyncAndQueueImageTask( // However, in the spec of updating the image data, the selection of image // source URL is in the asynchronous part (i.e. in a microtask), and so this // doesn't guarantee that the image style is correct after we flush the style - // synchornously. So here we update the responsive source synchronously always + // synchronously. So here we update the responsive source synchronously always // to make sure the image source is always up-to-date after each DOM mutation. // Spec issue: https://github.com/whatwg/html/issues/8207. - const bool changed = UpdateResponsiveSource(aSkippedSource); + UpdateResponsiveSource(aSkippedSource); - // If loading is temporarily disabled, we don't want to queue tasks - // that may then run when loading is re-enabled. + // If loading is temporarily disabled, we don't want to queue tasks that may + // then run when loading is re-enabled. + // Roughly step 1 and 2. + // FIXME(emilio): Would be great to do this more per-spec. We don't cancel + // existing loads etc. if (!LoadingEnabled() || !ShouldLoadImage()) { return; } // Ensure that we don't overwrite a previous load request that requires // a complete load to occur. - bool alwaysLoad = aAlwaysLoad; - if (mPendingImageLoadTask) { - alwaysLoad = alwaysLoad || mPendingImageLoadTask->AlwaysLoad(); - } + const bool alwaysLoad = aAlwaysLoad || (mPendingImageLoadTask && + mPendingImageLoadTask->AlwaysLoad()); - if (!changed && !alwaysLoad) { + // Steps 5 and 7 (sync cache check for src). + const bool shouldLoadSync = [&] { + if (HaveSrcsetOrInPicture()) { + return false; + } + if (!mSrcURI) { + // NOTE(emilio): we need to also do a sync check for empty / invalid src, + // see https://github.com/whatwg/html/issues/2429 + return true; + } + return nsContentUtils::IsImageAvailable( + this, mSrcURI, mSrcTriggeringPrincipal, GetCORSMode()); + }(); + + if (shouldLoadSync) { + if (!nsContentUtils::IsSafeToRunScript()) { + // If not safe to run script, we should do the sync load task as soon as + // possible instead. This prevents unsound state changes from frame + // construction and such. + nsContentUtils::AddScriptRunner( + NewRunnableMethod( + "HTMLImageElement::UpdateSourceSyncAndQueueImageTask", this, + &HTMLImageElement::UpdateSourceSyncAndQueueImageTask, aAlwaysLoad, + nullptr)); + return; + } + + if (mLazyLoading && mSrcURI) { + StopLazyLoading(StartLoad::No); + } + mPendingImageLoadTask = nullptr; + LoadSelectedImage(alwaysLoad); return; } - QueueImageLoadTask(alwaysLoad); -} - -bool HTMLImageElement::HaveSrcsetOrInPicture() { - if (HasAttr(nsGkAtoms::srcset)) { - return true; + if (mLazyLoading) { + // This check is not in the spec, but it is just a performance optimization. + // The reasoning for why it is sound is that we early-return from the image + // task when lazy loading, and that StopLazyLoading makes us queue a new + // task (which will implicitly cancel all the pre-existing tasks). + return; } - return IsInPicture(); + RefPtr task = new ImageLoadTask(this, alwaysLoad, mUseUrgentStartForChannel); + mPendingImageLoadTask = task; + // The task checks this to determine if it was the last queued event, and so + // earlier tasks are implicitly canceled. + CycleCollectedJSContext::Get()->DispatchToMicroTask(task.forget()); } -bool HTMLImageElement::InResponsiveMode() { - // When we lose srcset or leave a element, the fallback to img.src - // will happen from the microtask, and we should behave responsively in the - // interim - return mResponsiveSelector || mPendingImageLoadTask || - HaveSrcsetOrInPicture(); +bool HTMLImageElement::HaveSrcsetOrInPicture() const { + return HasAttr(nsGkAtoms::srcset) || IsInPicture(); } bool HTMLImageElement::SelectedSourceMatchesLast(nsIURI* aSelectedSource) { @@ -861,10 +777,9 @@ bool HTMLImageElement::SelectedSourceMatchesLast(nsIURI* aSelectedSource) { equal; } -nsresult HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify, - bool aAlwaysLoad) { - // In responsive mode, we have to make sure we ran the full selection algrithm - // before loading the selected image. +void HTMLImageElement::LoadSelectedImage(bool aAlwaysLoad) { + // In responsive mode, we have to make sure we ran the full selection + // algorithm before loading the selected image. // Use this assertion to catch any cases we missed. MOZ_ASSERT(!UpdateResponsiveSource(), "The image source should be the same because we update the " @@ -908,33 +823,30 @@ nsresult HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify, // to nsImageFrame::NotifyNewCurrentRequest, which takes care of that for // us. SetDensity(currentDensity); - return NS_OK; + return; } - // Before we actually defer the lazy-loading if (mLazyLoading) { - if (!selectedSource || - !nsContentUtils::IsImageAvailable(this, selectedSource, - triggeringPrincipal, GetCORSMode())) { - return NS_OK; - } - StopLazyLoading(StartLoading::No); + return; } nsresult rv = NS_ERROR_FAILURE; + const bool kNotify = true; // src triggers an error event on invalid URI, unlike other loads. if (selectedSource || hasSrc) { - rv = LoadImage(selectedSource, aForce, aNotify, type, triggeringPrincipal); + // We can pass true for aForce because we already do a manual check for + // SelectedSourceMatchesLast. + rv = LoadImage(selectedSource, /* aForce = */ true, kNotify, type, + triggeringPrincipal); } mLastSelectedSource = selectedSource; mCurrentDensity = currentDensity; if (NS_FAILED(rv)) { - CancelImageRequests(aNotify); + CancelImageRequests(kNotify); } - return rv; } void HTMLImageElement::PictureSourceSrcsetChanged(nsIContent* aSourceNode, @@ -963,9 +875,11 @@ void HTMLImageElement::PictureSourceSrcsetChanged(nsIContent* aSourceNode, mInDocResponsiveContent = true; } - // This always triggers the image update steps per the spec, even if - // we are not using this source. - UpdateSourceSyncAndQueueImageTask(true); + // This always triggers the image update steps per the spec, even if we are + // not using this source. + if (aNotify) { + UpdateSourceSyncAndQueueImageTask(true); + } } void HTMLImageElement::PictureSourceSizesChanged(nsIContent* aSourceNode, @@ -985,7 +899,9 @@ void HTMLImageElement::PictureSourceSizesChanged(nsIContent* aSourceNode, // This always triggers the image update steps per the spec, even if // we are not using this source. - UpdateSourceSyncAndQueueImageTask(true); + if (aNotify) { + UpdateSourceSyncAndQueueImageTask(true); + } } void HTMLImageElement::PictureSourceMediaOrTypeChanged(nsIContent* aSourceNode, @@ -995,7 +911,9 @@ void HTMLImageElement::PictureSourceMediaOrTypeChanged(nsIContent* aSourceNode, // This always triggers the image update steps per the spec, even if // we are not switching to/from this source - UpdateSourceSyncAndQueueImageTask(true); + if (aNotify) { + UpdateSourceSyncAndQueueImageTask(true); + } } void HTMLImageElement::PictureSourceDimensionChanged( @@ -1012,18 +930,24 @@ void HTMLImageElement::PictureSourceDimensionChanged( } } -void HTMLImageElement::PictureSourceAdded(HTMLSourceElement* aSourceNode) { +void HTMLImageElement::PictureSourceAdded(bool aNotify, + HTMLSourceElement* aSourceNode) { MOZ_ASSERT(!aSourceNode || IsPreviousSibling(aSourceNode, this), "Should not be getting notifications for non-previous-siblings"); - UpdateSourceSyncAndQueueImageTask(true); + if (aNotify) { + UpdateSourceSyncAndQueueImageTask(true); + } } -void HTMLImageElement::PictureSourceRemoved(HTMLSourceElement* aSourceNode) { +void HTMLImageElement::PictureSourceRemoved(bool aNotify, + HTMLSourceElement* aSourceNode) { MOZ_ASSERT(!aSourceNode || IsPreviousSibling(aSourceNode, this), "Should not be getting notifications for non-previous-siblings"); - UpdateSourceSyncAndQueueImageTask(true, aSourceNode); + if (aNotify) { + UpdateSourceSyncAndQueueImageTask(true, aSourceNode); + } } bool HTMLImageElement::UpdateResponsiveSource( @@ -1209,7 +1133,8 @@ bool HTMLImageElement::SelectSourceForTagWithAttrs( return false; } - // Using srcset or picture , build a responsive selector for this tag. + // Using srcset or picture , build a responsive selector for this + // tag. RefPtr sel = new ResponsiveImageSelector(aDocument); sel->SetCandidatesFromSourceSet(aSrcsetAttr); @@ -1272,24 +1197,7 @@ void HTMLImageElement::SetLazyLoading() { UpdateImageState(true); } -void HTMLImageElement::StartLoadingIfNeeded() { - if (!LoadingEnabled() || !ShouldLoadImage()) { - return; - } - - // Use script runner for the case the adopt is from appendChild. - // Bug 1076583 - We still behave synchronously in the non-responsive case - nsContentUtils::AddScriptRunner( - InResponsiveMode() - ? NewRunnableMethod("dom::HTMLImageElement::QueueImageLoadTask", - this, &HTMLImageElement::QueueImageLoadTask, - true) - : NewRunnableMethod("dom::HTMLImageElement::MaybeLoadImage", - this, &HTMLImageElement::MaybeLoadImage, - true)); -} - -void HTMLImageElement::StopLazyLoading(StartLoading aStartLoading) { +void HTMLImageElement::StopLazyLoading(StartLoad aStartLoad) { if (!mLazyLoading) { return; } @@ -1299,8 +1207,8 @@ void HTMLImageElement::StopLazyLoading(StartLoading aStartLoading) { obs->Unobserve(*this); } - if (aStartLoading == StartLoading::Yes) { - StartLoadingIfNeeded(); + if (aStartLoad == StartLoad::Yes) { + UpdateSourceSyncAndQueueImageTask(true); } } @@ -1372,15 +1280,6 @@ void HTMLImageElement::SetDensity(double aDensity) { } } -void HTMLImageElement::QueueImageLoadTask(bool aAlwaysLoad) { - RefPtr task = - new ImageLoadTask(this, aAlwaysLoad, mUseUrgentStartForChannel); - // The task checks this to determine if it was the last - // queued event, and so earlier tasks are implicitly canceled. - mPendingImageLoadTask = task; - CycleCollectedJSContext::Get()->DispatchToMicroTask(task.forget()); -} - FetchPriority HTMLImageElement::GetFetchPriorityForImage() const { return nsGenericHTMLElement::GetFetchPriority(); } diff --git a/dom/html/HTMLImageElement.h b/dom/html/HTMLImageElement.h index 1097d1fb048cf..9bfe434e9b6b7 100644 --- a/dom/html/HTMLImageElement.h +++ b/dom/html/HTMLImageElement.h @@ -79,11 +79,8 @@ class HTMLImageElement final : public nsGenericHTMLElement, nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override; void NodeInfoChanged(Document* aOldDoc) override; - nsresult CopyInnerTo(HTMLImageElement* aDest); - void MaybeLoadImage(bool aAlwaysForceLoad); - bool IsMap() { return GetBoolAttr(nsGkAtoms::ismap); } void SetIsMap(bool aIsMap, ErrorResult& aError) { SetHTMLBoolAttr(nsGkAtoms::ismap, aIsMap, aError); @@ -255,9 +252,8 @@ class HTMLImageElement final : public nsGenericHTMLElement, const nsAString& aTypeAttr, const nsAString& aMediaAttr, nsAString& aResult); - enum class FromIntersectionObserver : bool { No, Yes }; - enum class StartLoading : bool { No, Yes }; - void StopLazyLoading(StartLoading); + enum class StartLoad : bool { No, Yes }; + void StopLazyLoading(StartLoad = StartLoad::Yes); // This is used when restyling, for retrieving the extra style from the source // element. @@ -270,28 +266,19 @@ class HTMLImageElement final : public nsGenericHTMLElement, // Update the responsive source synchronously and 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 - // image load synchronously. void UpdateSourceSyncAndQueueImageTask( bool aAlwaysLoad, const HTMLSourceElement* aSkippedSource = nullptr); // True if we have a srcset attribute or a parent, regardless of if // any valid responsive sources were parsed from either. - bool HaveSrcsetOrInPicture(); - - // True if we are using the newer image loading algorithm. This will be the - // only mode after Bug 1076583 - bool InResponsiveMode(); + bool HaveSrcsetOrInPicture() const; // True if the given URL equals the last URL that was loaded by this element. bool SelectedSourceMatchesLast(nsIURI* aSelectedSource); // Load the current mResponsiveSelector (responsive mode) or src attr image. // Note: This doesn't run the full selection for the responsive selector. - nsresult LoadSelectedImage(bool aForce, bool aNotify, bool aAlwaysLoad); + void LoadSelectedImage(bool aAlwaysLoad); // True if this string represents a type we would support on static bool SupportedPictureSourceType(const nsAString& aType); @@ -310,9 +297,11 @@ class HTMLImageElement final : public nsGenericHTMLElement, void PictureSourceDimensionChanged(HTMLSourceElement* aSourceNode, bool aNotify); - void PictureSourceAdded(HTMLSourceElement* aSourceNode = nullptr); + void PictureSourceAdded(bool aNotify, + HTMLSourceElement* aSourceNode = nullptr); // This should be called prior to the unbind, such that nextsibling works - void PictureSourceRemoved(HTMLSourceElement* aSourceNode = nullptr); + void PictureSourceRemoved(bool aNotify, + HTMLSourceElement* aSourceNode = nullptr); // Re-evaluates all source nodes (picture ,) and finds // the best source set for mResponsiveSelector. If a better source @@ -397,8 +386,6 @@ class HTMLImageElement final : public nsGenericHTMLElement, // Set this image as a lazy load image due to loading="lazy". void SetLazyLoading(); - void StartLoadingIfNeeded(); - bool IsInPicture() const { return GetParentElement() && GetParentElement()->IsHTMLElement(nsGkAtoms::picture); diff --git a/dom/html/HTMLPictureElement.cpp b/dom/html/HTMLPictureElement.cpp index 45b1e4e3e3f25..d14726a3c1d04 100644 --- a/dom/html/HTMLPictureElement.cpp +++ b/dom/html/HTMLPictureElement.cpp @@ -32,14 +32,14 @@ void HTMLPictureElement::RemoveChildNode(nsIContent* aKid, bool aNotify) { MOZ_ASSERT(aKid); if (auto* img = HTMLImageElement::FromNode(aKid)) { - img->PictureSourceRemoved(); + img->PictureSourceRemoved(aNotify); } else if (auto* source = HTMLSourceElement::FromNode(aKid)) { // Find all img siblings after this to notify them of its demise nsCOMPtr nextSibling = source->GetNextSibling(); if (nextSibling && nextSibling->GetParentNode() == this) { do { if (auto* img = HTMLImageElement::FromNode(nextSibling)) { - img->PictureSourceRemoved(source); + img->PictureSourceRemoved(aNotify, source); } } while ((nextSibling = nextSibling->GetNextSibling())); } @@ -57,14 +57,14 @@ void HTMLPictureElement::InsertChildBefore(nsIContent* aKid, } if (auto* img = HTMLImageElement::FromNode(aKid)) { - img->PictureSourceAdded(); + img->PictureSourceAdded(aNotify); } else if (auto* source = HTMLSourceElement::FromNode(aKid)) { // Find all img siblings after this to notify them of its insertion nsCOMPtr nextSibling = source->GetNextSibling(); if (nextSibling && nextSibling->GetParentNode() == this) { do { if (auto* img = HTMLImageElement::FromNode(nextSibling)) { - img->PictureSourceAdded(source); + img->PictureSourceAdded(aNotify, source); } } while ((nextSibling = nextSibling->GetNextSibling())); } diff --git a/dom/tests/mochitest/general/test_img_mutations.html b/dom/tests/mochitest/general/test_img_mutations.html index 88cb40e1814f2..6e953e8c0050e 100644 --- a/dom/tests/mochitest/general/test_img_mutations.html +++ b/dom/tests/mochitest/general/test_img_mutations.html @@ -49,39 +49,50 @@ } } function expectEvents(loads, errors, callback) { - if (!loads && !errors) { - setTimeout(callback, 0); - } else { - expectingLoads += loads; - expectingErrors += errors; - info("Waiting for " + expectingLoads + " load and " + expectingErrors + " error events"); - afterExpectCallback = callback; - } + let p = new Promise(resolve => { + if (!loads && !errors) { + setTimeout(resolve, 0); + } else { + expectingLoads += loads; + expectingErrors += errors; + info("Waiting for " + expectingLoads + " load and " + expectingErrors + " error events"); + afterExpectCallback = resolve; + } + }); + return p.then(() => callback && callback()); } // // Test that img.src still does some work synchronously per the older spec (bug 1076583) // - tests.push(function test1() { + tests.push(async function test1() { info("test 1"); img.src = testPNG50; - is(img.currentSrc, testPNG50, "Should have synchronously selected source"); + is(img.currentSrc, "", "Should not have synchronously selected source"); + + await expectEvents(1, 0); + is(img.currentSrc, testPNG50, "Should now have testPNG50 as current request"); // Assigning a wrong URL should not trigger error event (bug 1321300). img.src = '//:0'; // Wrong URL + is(img.currentSrc, "", "Should have dropped current request sync"); img.src = "non_existent_image.404"; - ok(img.currentSrc.endsWith("non_existent_image.404"), "Should have synchronously selected source"); + is(img.currentSrc, "", "Should still have empty current request"); + + await expectEvents(0, 1); + ok(img.currentSrc.endsWith("non_existent_image.404"), "Should have asynchronously selected source"); img.removeAttribute("src"); - is(img.currentSrc, '', "Should have dropped currentSrc"); + is(img.currentSrc, "", "Should have dropped currentSrc sync"); // Load another image while previous load is still pending img.src = testPNG200; - is(img.currentSrc, testPNG200, "Should have synchronously selected source"); + is(img.currentSrc, "", "Should asynchronously load selected source"); - // No events should have fired synchronously, now we should get just one load (and no 404 error) - expectEvents(1, 0, nextTest); + await expectEvents(1, 0); + is(img.currentSrc, testPNG200, "Should have asynchronously loaded selected source"); + nextTest(); }); @@ -193,26 +204,25 @@ }); // Removing srcset attr should async switch back to src - tests.push(function () { + tests.push(async function () { info("test 10"); is(img.currentSrc, testPNG200, "Should have testPNG200 as current request"); img.removeAttribute("srcset"); - is(img.currentSrc, testPNG200, "Should still have testPNG200 as current request"); + is(img.currentSrc, testPNG100, "Should testPNG100 as current request (hits sync load case for src)"); - expectEvents(1, 0, function() { - is(img.currentSrc, testPNG100, "Should now have testPNG100 as current request"); + await expectEvents(1, 0); + is(img.currentSrc, testPNG100, "Should now have testPNG100 as current request"); - expectEvents(0, 0, nextTest); - }); + expectEvents(0, 0, nextTest); }); function nextTest() { if (tests.length) { // Spin event loop to make sure no unexpected image events are // pending (unexpected events will assert in the handlers) - setTimeout(function() { - (tests.shift())(); + setTimeout(async function() { + await (tests.shift())(); }, 0); } else { // Remove the event listeners to prevent the prefenv being popped from diff --git a/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-cross-origin-image-from-script.sub.html.ini b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-cross-origin-image-from-script.sub.html.ini index 53511670cefd9..f89c598a39ba5 100644 --- a/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-cross-origin-image-from-script.sub.html.ini +++ b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-cross-origin-image-from-script.sub.html.ini @@ -1,3 +1,3 @@ [securitypolicyviolation-block-cross-origin-image-from-script.sub.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] + [Non-redirected cross-origin URLs are not stripped.] + expected: FAIL diff --git a/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-cross-origin-image.sub.html.ini b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-cross-origin-image.sub.html.ini new file mode 100644 index 0000000000000..3d3531dc0b55a --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-cross-origin-image.sub.html.ini @@ -0,0 +1,3 @@ +[securitypolicyviolation-block-cross-origin-image.sub.html] + [Non-redirected cross-origin URLs are not stripped.] + expected: FAIL diff --git a/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-image-from-script.sub.html.ini b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-image-from-script.sub.html.ini index 1383fa78064a1..e3ca9694e1cf3 100644 --- a/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-image-from-script.sub.html.ini +++ b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-image-from-script.sub.html.ini @@ -1,3 +1,3 @@ [securitypolicyviolation-block-image-from-script.sub.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] + [Non-redirected cross-origin URLs are not stripped.] + expected: FAIL diff --git a/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-image.sub.html.ini b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-image.sub.html.ini new file mode 100644 index 0000000000000..900d04f76cb28 --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-image.sub.html.ini @@ -0,0 +1,3 @@ +[securitypolicyviolation-block-image.sub.html] + [Non-redirected same-origin URLs are not stripped.] + expected: FAIL diff --git a/testing/web-platform/meta/html/semantics/embedded-content/the-img-element/list-of-available-images-matching.https.html.ini b/testing/web-platform/meta/html/semantics/embedded-content/the-img-element/list-of-available-images-matching.https.html.ini index 9dc217e598c1e..6a938fb26c771 100644 --- a/testing/web-platform/meta/html/semantics/embedded-content/the-img-element/list-of-available-images-matching.https.html.ini +++ b/testing/web-platform/meta/html/semantics/embedded-content/the-img-element/list-of-available-images-matching.https.html.ini @@ -2,12 +2,6 @@ expected: if not tsan and (processor == "x86") and not debug: [OK, TIMEOUT] if tsan: CRASH - [list of available images tuple-matching logic] - expected: - if fission and (processor == "x86") and not debug: [FAIL, NOTRUN] - if not fission and (os == "android") and debug: [FAIL, PASS] - if not fission and (os == "linux"): [FAIL, PASS] - FAIL [registering service worker] expected: diff --git a/testing/web-platform/meta/html/semantics/embedded-content/the-img-element/update-the-image-data/current-request-microtask.html.ini b/testing/web-platform/meta/html/semantics/embedded-content/the-img-element/update-the-image-data/current-request-microtask.html.ini deleted file mode 100644 index 9fd84a88066d6..0000000000000 --- a/testing/web-platform/meta/html/semantics/embedded-content/the-img-element/update-the-image-data/current-request-microtask.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[current-request-microtask.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] - [currentSrc is updated only after the microtask that updates the current request is run] - expected: FAIL diff --git a/toolkit/components/extensions/test/mochitest/test_ext_web_accessible_incognito.html b/toolkit/components/extensions/test/mochitest/test_ext_web_accessible_incognito.html index 1009eb049644b..2b414d0c61f4b 100644 --- a/toolkit/components/extensions/test/mochitest/test_ext_web_accessible_incognito.html +++ b/toolkit/components/extensions/test/mochitest/test_ext_web_accessible_incognito.html @@ -146,10 +146,10 @@ await pb_extension.startup(); consoleMonitor.start([ - {message: /may not load or link to.*image.png/}, {message: /may not load or link to.*test_script.js/}, {message: /\ source URI is not allowed in this document/}, {message: /may not load or link to.*accessible.html/}, + {message: /may not load or link to.*image.png/}, ]); pb_extension.sendMessage("start", baseUrl);