Bug 1658202 - move flushes caused by closing the stream away from the main thread, r=valentin

Depends on D88730

Differential Revision: https://phabricator.services.mozilla.com/D88731
This commit is contained in:
Gijs Kruitbosch 2020-09-02 23:15:21 +00:00
Родитель dd70279b17
Коммит 58651be5dd
3 изменённых файлов: 39 добавлений и 7 удалений

Просмотреть файл

@ -889,8 +889,34 @@ NS_IMETHODIMP nsWebBrowserPersist::OnStopRequest(nsIRequest* request,
SendErrorStatusChange(true, status, request, data->mFile);
}
// If there is a stream ref and we weren't canceled,
// close it away from the main thread.
// We don't do this when there's an error/cancelation,
// because our consumer may try to delete the file, which will error
// if we're still holding on to it, so we have to close it pronto.
{
MutexAutoLock lock(data->mStreamMutex);
if (data->mStream && NS_SUCCEEDED(status) && !mCancel) {
if (!mBackgroundQueue) {
nsresult rv = NS_CreateBackgroundTaskQueue(
"WebBrowserPersist", getter_AddRefs(mBackgroundQueue));
if (NS_FAILED(rv)) {
return rv;
}
}
// Now steal the stream ref and close it away from the main thread,
// keeping the promise around so we don't finish before all files
// are flushed and closed.
mFileClosePromises.AppendElement(InvokeAsync(
mBackgroundQueue, __func__, [stream = std::move(data->mStream)]() {
nsresult rv = stream->Close();
// We don't care if closing failed; we don't care in the
// destructor either...
return ClosePromise::CreateAndResolve(rv, __func__);
}));
}
}
MutexAutoLock lock(mOutputMapMutex);
// This will automatically close the output stream
mOutputMap.Remove(keyPtr);
} else {
// if we didn't find the data in mOutputMap, try mUploadList
@ -2275,7 +2301,14 @@ void nsWebBrowserPersist::EndDownload(nsresult aResult) {
if (NS_SUCCEEDED(mPersistResult) && NS_FAILED(aResult)) {
mPersistResult = aResult;
}
ClosePromise::All(GetCurrentSerialEventTarget(), mFileClosePromises)
->Then(GetCurrentSerialEventTarget(), __func__,
[self = RefPtr{this}, aResult]() {
self->EndDownloadInternal(aResult);
});
}
void nsWebBrowserPersist::EndDownloadInternal(nsresult aResult) {
// mCompleted needs to be set before issuing the stop notification.
// (Bug 1224437)
mCompleted = true;

Просмотреть файл

@ -31,6 +31,8 @@
class nsIStorageStream;
class nsIWebBrowserPersistDocument;
using ClosePromise = mozilla::MozPromise<nsresult, nsresult, true>;
class nsWebBrowserPersist final : public nsIInterfaceRequestor,
public nsIWebBrowserPersist,
public nsIStreamListener,
@ -124,8 +126,9 @@ class nsWebBrowserPersist final : public nsIInterfaceRequestor,
nsresult FixRedirectedChannelEntry(nsIChannel* aNewChannel);
void EndDownload(nsresult aResult);
void FinishDownload();
void EndDownload(nsresult aResult);
void EndDownloadInternal(nsresult aResult);
void SerializeNextFile();
void CalcTotalProgress();
@ -153,6 +156,7 @@ class nsWebBrowserPersist final : public nsIInterfaceRequestor,
nsClassHashtable<nsISupportsHashKey, OutputData> mOutputMap;
nsClassHashtable<nsISupportsHashKey, UploadData> mUploadList;
nsCOMPtr<nsISerialEventTarget> mBackgroundQueue;
nsTArray<RefPtr<ClosePromise>> mFileClosePromises;
nsClassHashtable<nsCStringHashKey, URIData> mURIMap;
nsCOMPtr<nsIWebBrowserPersistURIMap> mFlatURIMap;
nsTArray<mozilla::UniquePtr<WalkData>> mWalkStack;

Просмотреть файл

@ -122,11 +122,6 @@ DownloadLegacyTransfer.prototype = {
// Only cancel if the object executing the download is still running.
if (this._cancelable && !this._componentFailed) {
this._cancelable.cancel(Cr.NS_ERROR_ABORT);
if (this._cancelable instanceof Ci.nsIWebBrowserPersist) {
// This component will not send the STATE_STOP notification.
download.saver.onTransferFinished(Cr.NS_ERROR_ABORT);
this._cancelable = null;
}
}
});
})