Fix link preview race condition
This commit is contained in:
parent
66d9bb8418
commit
6642652bdb
3 changed files with 77 additions and 2 deletions
|
@ -597,5 +597,9 @@ export async function fetchLinkPreviewImage(
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (abortSignal.aborted) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return { data, contentType };
|
return { data, contentType };
|
||||||
}
|
}
|
||||||
|
|
|
@ -1354,5 +1354,70 @@ describe('link preview fetching', () => {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("doesn't read the image if the request was aborted before reading started", async () => {
|
||||||
|
const abortController = new AbortController();
|
||||||
|
|
||||||
|
const fixture = await readFixture('kitten-1-64-64.jpg');
|
||||||
|
|
||||||
|
const fakeFetch = stub().callsFake(() => {
|
||||||
|
const response = new Response(fixture, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'image/jpeg',
|
||||||
|
'Content-Length': fixture.length.toString(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
sinon
|
||||||
|
.stub(response, 'arrayBuffer')
|
||||||
|
.rejects(new Error('Should not be called'));
|
||||||
|
sinon.stub(response, 'blob').rejects(new Error('Should not be called'));
|
||||||
|
sinon.stub(response, 'text').rejects(new Error('Should not be called'));
|
||||||
|
sinon.stub(response, 'body').get(() => {
|
||||||
|
throw new Error('Should not be accessed');
|
||||||
|
});
|
||||||
|
|
||||||
|
abortController.abort();
|
||||||
|
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.isNull(
|
||||||
|
await fetchLinkPreviewImage(
|
||||||
|
fakeFetch,
|
||||||
|
'https://example.com/img',
|
||||||
|
abortController.signal
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null if the request was aborted after the image was read', async () => {
|
||||||
|
const abortController = new AbortController();
|
||||||
|
|
||||||
|
const fixture = await readFixture('kitten-1-64-64.jpg');
|
||||||
|
|
||||||
|
const fakeFetch = stub().callsFake(() => {
|
||||||
|
const response = new Response(fixture, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'image/jpeg',
|
||||||
|
'Content-Length': fixture.length.toString(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const oldArrayBufferMethod = response.arrayBuffer.bind(response);
|
||||||
|
sinon.stub(response, 'arrayBuffer').callsFake(async () => {
|
||||||
|
const data = await oldArrayBufferMethod();
|
||||||
|
abortController.abort();
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.isNull(
|
||||||
|
await fetchLinkPreviewImage(
|
||||||
|
fakeFetch,
|
||||||
|
'https://example.com/img',
|
||||||
|
abortController.signal
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4169,14 +4169,13 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
url,
|
url,
|
||||||
abortSignal
|
abortSignal
|
||||||
);
|
);
|
||||||
if (!linkPreviewMetadata) {
|
if (!linkPreviewMetadata || abortSignal.aborted) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const { title, imageHref, description, date } = linkPreviewMetadata;
|
const { title, imageHref, description, date } = linkPreviewMetadata;
|
||||||
|
|
||||||
let image;
|
let image;
|
||||||
if (
|
if (
|
||||||
!abortSignal.aborted &&
|
|
||||||
imageHref &&
|
imageHref &&
|
||||||
window.Signal.LinkPreviews.isLinkSafeToPreview(imageHref)
|
window.Signal.LinkPreviews.isLinkSafeToPreview(imageHref)
|
||||||
) {
|
) {
|
||||||
|
@ -4186,6 +4185,9 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
imageHref,
|
imageHref,
|
||||||
abortSignal
|
abortSignal
|
||||||
);
|
);
|
||||||
|
if (abortSignal.aborted) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (!fullSizeImage) {
|
if (!fullSizeImage) {
|
||||||
throw new Error('Failed to fetch link preview image');
|
throw new Error('Failed to fetch link preview image');
|
||||||
}
|
}
|
||||||
|
@ -4229,6 +4231,10 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (abortSignal.aborted) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
url,
|
url,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue