mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-19 07:26:26 +00:00
Bug 1800979 - Mark CSS image value loads as not cancelable. r=tnikkel
Yes, the test took 15 times as much as the fix. Differential Revision: https://phabricator.services.mozilla.com/D162474
This commit is contained in:
parent
6c0098d405
commit
d05b1727e9
@ -22,7 +22,6 @@
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::image;
|
||||
using mozilla::dom::Document;
|
||||
|
||||
// The split of imgRequestProxy and imgRequestProxyStatic means that
|
||||
// certain overridden functions need to be usable in the destructor.
|
||||
@ -109,6 +108,7 @@ imgRequestProxy::imgRequestProxy()
|
||||
mLoadFlags(nsIRequest::LOAD_NORMAL),
|
||||
mLockCount(0),
|
||||
mAnimationConsumers(0),
|
||||
mCancelable(true),
|
||||
mCanceled(false),
|
||||
mIsInLoadGroup(false),
|
||||
mForceDispatchLoadGroup(false),
|
||||
@ -462,12 +462,21 @@ NS_IMETHODIMP imgRequestProxy::CancelWithReason(nsresult aStatus,
|
||||
return CancelWithReasonImpl(aStatus, aReason);
|
||||
}
|
||||
|
||||
void imgRequestProxy::SetCancelable(bool aCancelable) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mCancelable = aCancelable;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
imgRequestProxy::Cancel(nsresult status) {
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!mCancelable)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
LOG_SCOPE(gImgLog, "imgRequestProxy::Cancel");
|
||||
|
||||
mCanceled = true;
|
||||
@ -494,6 +503,13 @@ imgRequestProxy::CancelAndForgetObserver(nsresult aStatus) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!mCancelable)) {
|
||||
MOZ_ASSERT(mCancelable,
|
||||
"Shouldn't try to cancel non-cancelable requests via "
|
||||
"CancelAndForgetObserver");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
LOG_SCOPE(gImgLog, "imgRequestProxy::CancelAndForgetObserver");
|
||||
|
||||
mCanceled = true;
|
||||
|
@ -111,6 +111,10 @@ class imgRequestProxy : public mozilla::PreloaderBase,
|
||||
void MarkValidating();
|
||||
void ClearValidating();
|
||||
|
||||
// Flags this image load as not cancelable temporarily. This is needed so that
|
||||
// stylesheets can be shared across documents properly, see bug 1800979.
|
||||
void SetCancelable(bool);
|
||||
|
||||
already_AddRefed<nsIEventTarget> GetEventTarget() const override;
|
||||
|
||||
// Removes all animation consumers that were created with
|
||||
@ -215,6 +219,7 @@ class imgRequestProxy : public mozilla::PreloaderBase,
|
||||
nsLoadFlags mLoadFlags;
|
||||
uint32_t mLockCount;
|
||||
uint32_t mAnimationConsumers;
|
||||
bool mCancelable : 1;
|
||||
bool mCanceled : 1;
|
||||
bool mIsInLoadGroup : 1;
|
||||
bool mForceDispatchLoadGroup : 1;
|
||||
|
@ -85,7 +85,13 @@ void ImageLoader::Init() {
|
||||
/* static */
|
||||
void ImageLoader::Shutdown() {
|
||||
for (const auto& entry : *sImages) {
|
||||
entry.GetKey()->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
||||
imgIRequest* imgRequest = entry.GetKey();
|
||||
// All the images we put in sImages are imgRequestProxy, see LoadImage, but
|
||||
// it's non-trivial to make the hash table to use that without changing a
|
||||
// lot of other code.
|
||||
auto* req = static_cast<imgRequestProxy*>(imgRequest);
|
||||
req->SetCancelable(true);
|
||||
req->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
||||
}
|
||||
|
||||
sImages = nullptr;
|
||||
@ -444,6 +450,10 @@ already_AddRefed<imgRequestProxy> ImageLoader::LoadImage(
|
||||
if (NS_FAILED(rv) || !request) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This image could be shared across documents, so its load cannot be
|
||||
// canceled, see bug 1800979.
|
||||
request->SetCancelable(false);
|
||||
sImages->GetOrInsertNew(request);
|
||||
return request.forget();
|
||||
}
|
||||
@ -467,6 +477,8 @@ void ImageLoader::UnloadImage(imgRequestProxy* aImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Now we want to really cancel the request.
|
||||
aImage->SetCancelable(true);
|
||||
aImage->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
||||
MOZ_DIAGNOSTIC_ASSERT(lookup.Data()->mImageLoaders.IsEmpty(),
|
||||
"Shouldn't be keeping references to any loader "
|
||||
|
@ -0,0 +1,5 @@
|
||||
<!doctype html>
|
||||
<title>CSS Test Reference</title>
|
||||
<style>
|
||||
:root { background-color: lime }
|
||||
</style>
|
@ -0,0 +1,49 @@
|
||||
<!doctype html>
|
||||
<html class="reftest-wait">
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Test: Canceled load in another page doesn't affect new stylesheet</title>
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<link rel="author" title="Mozilla" href="https://mozilla.org">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#background-image">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1800979">
|
||||
<link rel="match" href="background-image-shared-stylesheet-ref.html">
|
||||
<iframe></iframe>
|
||||
<script>
|
||||
const IMAGE_URI = new URL("/images/green.png", location.href).href + "?pipe=trickle(d2)&" + Math.random();
|
||||
const SHEET_URI = "data:text/css," + encodeURI(`:root{background-image: url('${IMAGE_URI}');}`);
|
||||
const iframe = document.querySelector("iframe");
|
||||
|
||||
function willNavigate() {
|
||||
// The child page has already loaded the stylesheet (guaranteed by the <script> rules)
|
||||
// and is about to navigate away. Trigger our stylesheet load and thus image
|
||||
// load when it does. The background-image should still apply to us.
|
||||
iframe.addEventListener("load", function() {
|
||||
let link = document.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = SHEET_URI;
|
||||
link.onload = function() {
|
||||
iframe.remove();
|
||||
// We need to also make sure that the image has actually finished to load,
|
||||
// so that the reftest screenshot can be taken.
|
||||
const image = new Image();
|
||||
image.onload = function() {
|
||||
document.documentElement.className = "";
|
||||
};
|
||||
image.src = IMAGE_URI;
|
||||
};
|
||||
document.head.appendChild(link);
|
||||
}, { once: true });
|
||||
}
|
||||
|
||||
onload = function() {
|
||||
document.querySelector("iframe").srcdoc = `
|
||||
<!doctype html>
|
||||
<link rel="stylesheet" href="${SHEET_URI}">
|
||||
<script>
|
||||
document.documentElement.getBoundingClientRect(); // Should trigger the image load.
|
||||
parent.willNavigate();
|
||||
window.location = "/css/reference/blank.html";
|
||||
</` + `script>
|
||||
`;
|
||||
};
|
||||
</script>
|
Loading…
x
Reference in New Issue
Block a user