mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Bug 1862059. Handle edge cases of svg images in multipart images. r=aosmond,gfx-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D192827
This commit is contained in:
parent
ba501d058d
commit
0f39860036
@ -42,6 +42,43 @@ class NextPartObserver : public IProgressObserver {
|
||||
mImage->RequestDecodeForSize(gfx::IntSize(0, 0),
|
||||
imgIContainer::FLAG_SYNC_DECODE);
|
||||
|
||||
if (mImage && mImage->GetType() == imgIContainer::TYPE_VECTOR) {
|
||||
// We don't want to make a pending part the current part until it has had
|
||||
// it's load event because when we transition from the current part to the
|
||||
// next part we remove the multipart image as an observer of the current
|
||||
// part and the progress tracker will send a fake load event with the
|
||||
// lastpart bit set whenever an observer is removed without having the
|
||||
// load complete progress. That fake load event with the lastpart bit set
|
||||
// will get out of the multipart image and to the imgRequestProxy and
|
||||
// further, which will make it look like we got the last part of the
|
||||
// multipart image and confuse things. If we get here then we are still
|
||||
// waiting to make mNextPart the current part, but we've gotten
|
||||
// OnDataAvailable for the part after mNextPart. That means we must have
|
||||
// gotten OnStopRequest for mNextPart; OnStopRequest calls
|
||||
// OnImageDataComplete. For raster images that are part of a multipart
|
||||
// image OnImageDataComplete will synchronously fire the load event
|
||||
// because we synchronously perform the metadata decode in that function,
|
||||
// because parts of multipart images have the transient flag set. So for
|
||||
// raster images we are assured that the load event has happened by this
|
||||
// point for mNextPart. For vector images there is no such luck because
|
||||
// OnImageDataComplete needs to wait for the load event in the underlying
|
||||
// svg document, which we can't force to happen synchronously. So we just
|
||||
// send a fake load event for mNextPart. We are the only listener for it
|
||||
// right now so it won't confuse anyone. When the real load event comes,
|
||||
// progress tracker won't send it out because it's already in the
|
||||
// progress. And nobody should be caring about load events on the current
|
||||
// part of multipart images since they might be sent multiple times or
|
||||
// might not be sent at all depending on timing. So this should be okay.
|
||||
|
||||
RefPtr<ProgressTracker> tracker = mImage->GetProgressTracker();
|
||||
if (tracker && !(tracker->GetProgress() & FLAG_LOAD_COMPLETE)) {
|
||||
Progress loadProgress =
|
||||
LoadCompleteProgress(/* aLastPart = */ false, /* aError = */ false,
|
||||
/* aStatus = */ NS_OK);
|
||||
tracker->SyncNotifyProgress(loadProgress | FLAG_SIZE_AVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
// RequestDecodeForSize() should've sent synchronous notifications that
|
||||
// would have caused us to call FinishObserving() (and null out mImage)
|
||||
// already. If for some reason it didn't, we should do so here.
|
||||
@ -57,9 +94,26 @@ class NextPartObserver : public IProgressObserver {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aType == imgINotificationObserver::FRAME_COMPLETE) {
|
||||
FinishObserving();
|
||||
if (aType != imgINotificationObserver::FRAME_COMPLETE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mImage && mImage->GetType() == imgIContainer::TYPE_VECTOR) {
|
||||
RefPtr<ProgressTracker> tracker = mImage->GetProgressTracker();
|
||||
if (tracker && !(tracker->GetProgress() & FLAG_LOAD_COMPLETE)) {
|
||||
// Vector images can send frame complete during loading (any mutation in
|
||||
// the underlying svg doc will call OnRenderingChange which sends frame
|
||||
// complete). Whereas raster images can only send frame complete before
|
||||
// the load event if there has been something to trigger a decode, but
|
||||
// we do not request a decode. So we will ignore this for vector images
|
||||
// so as to enforce the invariant described above in
|
||||
// BlockUntilDecodedAndFinishObserving that the current part always has
|
||||
// the load complete progress.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FinishObserving();
|
||||
}
|
||||
|
||||
virtual void OnLoadComplete(bool aLastPart) override {
|
||||
@ -84,6 +138,15 @@ class NextPartObserver : public IProgressObserver {
|
||||
RefPtr<ProgressTracker> tracker = mImage->GetProgressTracker();
|
||||
if (tracker->GetProgress() & FLAG_HAS_ERROR) {
|
||||
FinishObserving();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mImage && mImage->GetType() == imgIContainer::TYPE_VECTOR &&
|
||||
(tracker->GetProgress() & FLAG_FRAME_COMPLETE)) {
|
||||
// It's a vector image that we may have already got a frame complete
|
||||
// before load that we ignored (see Notify above). Now that we have the
|
||||
// load event too, we make this part current.
|
||||
FinishObserving();
|
||||
}
|
||||
}
|
||||
|
||||
|
15
image/test/crashtests/1862059-1.html
Normal file
15
image/test/crashtests/1862059-1.html
Normal file
@ -0,0 +1,15 @@
|
||||
<html class="reftest-wait">
|
||||
<img src="1862059-1.svg"></img>
|
||||
<script>
|
||||
let numTimes = 15;
|
||||
function doTest() {
|
||||
numTimes--;
|
||||
if (numTimes > 0) {
|
||||
window.requestAnimationFrame(doTest);
|
||||
} else {
|
||||
document.documentElement.className = "";
|
||||
}
|
||||
}
|
||||
window.addEventListener("MozReftestInvalidate", doTest);
|
||||
</script>
|
||||
</html>
|
43
image/test/crashtests/1862059-1.svg
Normal file
43
image/test/crashtests/1862059-1.svg
Normal file
@ -0,0 +1,43 @@
|
||||
--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>--BOUNDARYOMG
|
||||
Content-Type: image/svg+xml; charset=utf-8
|
||||
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg" fill="#F00"></svg>
|
3
image/test/crashtests/1862059-1.svg^headers^
Normal file
3
image/test/crashtests/1862059-1.svg^headers^
Normal file
@ -0,0 +1,3 @@
|
||||
HTTP 200 OK
|
||||
Content-Type: multipart/x-mixed-replace;boundary=BOUNDARYOMG
|
||||
Cache-Control: no-cache
|
@ -80,3 +80,4 @@ load 1814774.avif
|
||||
load 1817108.avif
|
||||
load 1848717-1.avif
|
||||
load 1852649.webp
|
||||
pref(widget.windows.window_occlusion_tracking.enabled,false) HTTP load 1862059-1.html
|
||||
|
Loading…
Reference in New Issue
Block a user