Bug 1434553 - Implement nsIInputStreamLength and nsIAsyncInputStreamLength - part 9 - necko and docShell, r=mayhemer, r=smaug

This commit is contained in:
Andrea Marchesini 2018-05-23 07:12:36 +02:00
Родитель 4d342e4ebf
Коммит 7dcc1b6880
24 изменённых файлов: 357 добавлений и 270 удалений

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

@ -1020,7 +1020,6 @@ nsDocShell::LoadURI(nsIURI* aURI,
nullptr, // No type hint
VoidString(), // No forced download
postStream,
-1, // XXXbaku
headersStream,
loadType,
nullptr, // No SHEntry
@ -4932,7 +4931,7 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
mozilla::net::RP_Unset,
nsContentUtils::GetSystemPrincipal(), nullptr,
INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
nullptr, VoidString(), nullptr, -1, nullptr,
nullptr, VoidString(), nullptr, nullptr,
LOAD_ERROR_PAGE, nullptr, true, VoidString(), this,
nullptr, nullptr, nullptr);
}
@ -5034,7 +5033,6 @@ nsDocShell::Reload(uint32_t aReloadFlags)
NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
VoidString(), // No forced download
nullptr, // No post data
-1, // No post data length
nullptr, // No headers data
loadType, // Load type
nullptr, // No SHEntry
@ -9145,7 +9143,6 @@ public:
uint32_t aFlags,
const char* aTypeHint,
nsIInputStream* aPostData,
int64_t aPostDataLength,
nsIInputStream* aHeadersData,
uint32_t aLoadType,
nsISHEntry* aSHEntry,
@ -9165,7 +9162,6 @@ public:
, mTriggeringPrincipal(aTriggeringPrincipal)
, mPrincipalToInherit(aPrincipalToInherit)
, mPostData(aPostData)
, mPostDataLength(aPostDataLength)
, mHeadersData(aHeadersData)
, mSHEntry(aSHEntry)
, mFlags(aFlags)
@ -9193,7 +9189,7 @@ public:
mFlags, EmptyString(),
mTypeHint.IsVoid() ? nullptr
: mTypeHint.get(),
VoidString(), mPostData, mPostDataLength,
VoidString(), mPostData,
mHeadersData, mLoadType, mSHEntry,
mFirstParty, mSrcdoc, mSourceDocShell,
mBaseURI, nullptr,
@ -9214,7 +9210,6 @@ private:
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
nsCOMPtr<nsIPrincipal> mPrincipalToInherit;
nsCOMPtr<nsIInputStream> mPostData;
int64_t mPostDataLength;
nsCOMPtr<nsIInputStream> mHeadersData;
nsCOMPtr<nsISHEntry> mSHEntry;
uint32_t mFlags;
@ -9265,7 +9260,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
const char* aTypeHint,
const nsAString& aFileName,
nsIInputStream* aPostData,
int64_t aPostDataLength,
nsIInputStream* aHeadersData,
uint32_t aLoadType,
nsISHEntry* aSHEntry,
@ -9617,7 +9611,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
aTypeHint,
VoidString(), // No forced download
aPostData,
aPostDataLength,
aHeadersData,
aLoadType,
aSHEntry,
@ -9708,7 +9701,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
new InternalLoadEvent(this, aURI, aOriginalURI, aResultPrincipalURI,
aLoadReplace, aReferrer, aReferrerPolicy,
aTriggeringPrincipal, principalToInherit,
aFlags, aTypeHint, aPostData, aPostDataLength,
aFlags, aTypeHint, aPostData,
aHeadersData, aLoadType, aSHEntry, aFirstParty,
aSrcdoc, aSourceDocShell, aBaseURI);
return DispatchToTabGroup(TaskCategory::Other, ev.forget());
@ -10231,7 +10224,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
!(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
aReferrerPolicy,
aTriggeringPrincipal, principalToInherit, aTypeHint,
aFileName, aPostData, aPostDataLength, aHeadersData,
aFileName, aPostData, aHeadersData,
aFirstParty, aDocShell, getter_AddRefs(req),
(aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
(aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0,
@ -10375,7 +10368,6 @@ nsDocShell::DoURILoad(nsIURI* aURI,
const char* aTypeHint,
const nsAString& aFileName,
nsIInputStream* aPostData,
int64_t aPostDataLength,
nsIInputStream* aHeadersData,
bool aFirstParty,
nsIDocShell** aDocShell,
@ -10811,7 +10803,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
}
// we really need to have a content type associated with this stream!!
postChannel->SetUploadStream(aPostData, EmptyCString(), aPostDataLength);
postChannel->SetUploadStream(aPostData, EmptyCString(), -1);
}
/* If there is a valid postdata *and* it is a History Load,
@ -12300,7 +12292,6 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
contentType.get(), // Type hint
VoidString(), // No forced file download
postData, // Post data stream
-1, // Post data stream length
nullptr, // No headers stream
aLoadType, // Load type
aEntry, // SHEntry
@ -13292,7 +13283,6 @@ public:
const char16_t* aTargetSpec,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
int64_t aPostDataStreamLength,
nsIInputStream* aHeadersDataStream,
bool aNoOpenerImplied,
bool aIsUserTriggered,
@ -13312,7 +13302,7 @@ public:
if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
mHandler->OnLinkClickSync(mContent, mURI,
mTargetSpec.get(), mFileName,
mPostDataStream, mPostDataStreamLength,
mPostDataStream,
mHeadersDataStream, mNoOpenerImplied,
nullptr, nullptr, mIsUserTriggered,
mTriggeringPrincipal);
@ -13326,7 +13316,6 @@ private:
nsString mTargetSpec;
nsString mFileName;
nsCOMPtr<nsIInputStream> mPostDataStream;
int64_t mPostDataStreamLength;
nsCOMPtr<nsIInputStream> mHeadersDataStream;
nsCOMPtr<nsIContent> mContent;
PopupControlState mPopupState;
@ -13342,7 +13331,6 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
const char16_t* aTargetSpec,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
int64_t aPostDataStreamLength,
nsIInputStream* aHeadersDataStream,
bool aNoOpenerImplied,
bool aIsUserTriggered,
@ -13354,7 +13342,6 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
, mTargetSpec(aTargetSpec)
, mFileName(aFileName)
, mPostDataStream(aPostDataStream)
, mPostDataStreamLength(aPostDataStreamLength)
, mHeadersDataStream(aHeadersDataStream)
, mContent(aContent)
, mPopupState(mHandler->mScriptGlobal->GetPopupControlState())
@ -13371,7 +13358,6 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
const char16_t* aTargetSpec,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
int64_t aPostDataStreamLength,
nsIInputStream* aHeadersDataStream,
bool aIsUserTriggered,
bool aIsTrusted,
@ -13418,8 +13404,7 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
nsCOMPtr<nsIRunnable> ev =
new OnLinkClickEvent(this, aContent, aURI, target.get(), aFileName,
aPostDataStream, aPostDataStreamLength,
aHeadersDataStream, noOpenerImplied,
aPostDataStream, aHeadersDataStream, noOpenerImplied,
aIsUserTriggered, aIsTrusted, aTriggeringPrincipal);
return DispatchToTabGroup(TaskCategory::UI, ev.forget());
}
@ -13438,7 +13423,6 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
const char16_t* aTargetSpec,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
int64_t aPostDataStreamLength,
nsIInputStream* aHeadersDataStream,
bool aNoOpenerImplied,
nsIDocShell** aDocShell,
@ -13599,7 +13583,6 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
NS_LossyConvertUTF16toASCII(typeHint).get(),
aFileName, // Download as file
aPostDataStream, // Post data stream
aPostDataStreamLength, // Post data stream length
aHeadersDataStream, // Headers stream
loadType, // Load type
nullptr, // No SHEntry

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

@ -208,7 +208,6 @@ public:
const char16_t* aTargetSpec,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
int64_t aPostDataStreamLength,
nsIInputStream* aHeadersDataStream,
bool aIsUserTriggered,
bool aIsTrusted,
@ -218,7 +217,6 @@ public:
const char16_t* aTargetSpec,
const nsAString& aFileName,
nsIInputStream* aPostDataStream = 0,
int64_t aPostDataStreamLength = -1,
nsIInputStream* aHeadersDataStream = 0,
bool aNoOpenerImplied = false,
nsIDocShell** aDocShell = 0,
@ -533,7 +531,6 @@ private: // member functions
const char* aTypeHint,
const nsAString& aFileName,
nsIInputStream* aPostData,
int64_t aPostDataLength,
nsIInputStream* aHeadersData,
bool aFirstParty,
nsIDocShell** aDocShell,

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

@ -188,8 +188,6 @@ interface nsIDocShell : nsIDocShellTreeItem
* @param aFileName - Non-null when the link should be downloaded as
the given filename.
* @param aPostDataStream - Post data stream (if POSTing)
* @param aPostDataStreamLength - Post data stream length. Use -1 if the length
of the stream is unknown.
* @param aHeadersStream - Stream containing "extra" request headers...
* @param aLoadFlags - Flags to modify load behaviour. Flags are defined
* in nsIWebNavigation.
@ -215,7 +213,6 @@ interface nsIDocShell : nsIDocShellTreeItem
in string aTypeHint,
in AString aFileName,
in nsIInputStream aPostDataStream,
in long long aPostDataStreamLength,
in nsIInputStream aHeadersStream,
in unsigned long aLoadFlags,
in nsISHEntry aSHEntry,

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

@ -35,8 +35,6 @@ public:
* string)
* @param aFileName non-null when the link should be downloaded as the given file
* @param aPostDataStream the POST data to send
* @param aPostDataStreamLength the POST data length. Use -1 if the length is
* unknown.
* @param aHeadersDataStream ???
* @param aIsTrusted false if the triggerer is an untrusted DOM event.
* @param aTriggeringPrincipal, if not passed explicitly we fall back to
@ -47,7 +45,6 @@ public:
const char16_t* aTargetSpec,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
int64_t aPostDataStreamLength,
nsIInputStream* aHeadersDataStream,
bool aIsUserTriggered,
bool aIsTrusted,
@ -65,7 +62,6 @@ public:
* string)
* @param aFileName non-null when the link should be downloaded as the given file
* @param aPostDataStream the POST data to send
* @param aPostDataStreamLength the POST data length
* @param aHeadersDataStream ???
* @param aNoOpenerImplied if the link implies "noopener"
* @param aDocShell (out-param) the DocShell that the request was opened on
@ -78,7 +74,6 @@ public:
const char16_t* aTargetSpec,
const nsAString& aFileName,
nsIInputStream* aPostDataStream = 0,
int64_t aPostDataStreamLength = -1,
nsIInputStream* aHeadersDataStream = 0,
bool aNoOpenerImplied = false,
nsIDocShell** aDocShell = 0,

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

@ -101,7 +101,6 @@ NS_INTERFACE_MAP_END
nsresult
FormData::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream,
int64_t* aPostDataStreamLength,
nsCOMPtr<nsIURI>& aOutURI)
{
NS_NOTREACHED("Shouldn't call FormData::GetEncodedSubmission");

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

@ -107,7 +107,7 @@ public:
// HTMLFormSubmission
virtual nsresult
GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
int64_t* aPostDataStreamLength, nsCOMPtr<nsIURI>& aOutURI) override;
nsCOMPtr<nsIURI>& aOutURI) override;
virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue) override

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

@ -5538,7 +5538,7 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
handler->OnLinkClick(aContent, aLinkURI,
fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(),
fileName, nullptr, -1, nullptr, EventStateManager::IsHandlingUserInput(),
fileName, nullptr, nullptr, EventStateManager::IsHandlingUserInput(),
aIsTrusted, aContent->NodePrincipal());
}
}

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

@ -158,8 +158,14 @@ IPCBlobInputStreamParent::RecvLengthNeeded()
return IPC_OK();
}
int64_t length = -1;
if (InputStreamLengthHelper::GetSyncLength(stream, &length)) {
Unused << SendLengthReady(length);
return IPC_OK();
}
RefPtr<IPCBlobInputStreamParent> self = this;
InputStreamLengthHelper::GetLength(stream, [self](int64_t aLength) {
InputStreamLengthHelper::GetAsyncLength(stream, [self](int64_t aLength) {
if (self->mContentManager || self->mPBackgroundManager) {
Unused << self->SendLengthReady(aLength);
}

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

@ -771,17 +771,15 @@ HTMLFormElement::SubmitSubmission(HTMLFormSubmission* aFormSubmission)
nullptr, doc);
nsCOMPtr<nsIInputStream> postDataStream;
int64_t postDataStreamLength = -1;
rv = aFormSubmission->GetEncodedSubmission(actionURI,
getter_AddRefs(postDataStream),
&postDataStreamLength,
actionURI);
NS_ENSURE_SUBMIT_SUCCESS(rv);
rv = linkHandler->OnLinkClickSync(this, actionURI,
target.get(),
VoidString(),
postDataStream, postDataStreamLength,
postDataStream,
nullptr, false,
getter_AddRefs(docShell),
getter_AddRefs(mSubmittingRequest),

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

@ -114,7 +114,7 @@ public:
virtual nsresult
GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
int64_t* aPostDataStreamLength, nsCOMPtr<nsIURI>& aOutURI) override;
nsCOMPtr<nsIURI>& aOutURI) override;
protected:
@ -269,14 +269,12 @@ HandleMailtoSubject(nsCString& aPath)
nsresult
FSURLEncoded::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream,
int64_t* aPostDataStreamLength,
nsCOMPtr<nsIURI>& aOutURI)
{
nsresult rv = NS_OK;
aOutURI = aURI;
*aPostDataStream = nullptr;
*aPostDataStreamLength = -1;
if (mMethod == NS_FORM_METHOD_POST) {
@ -302,7 +300,6 @@ FSURLEncoded::GetEncodedSubmission(nsIURI* aURI,
.SetPathQueryRef(path)
.Finalize(aOutURI);
} else {
uint32_t queryStringLength = mQueryString.Length();
nsCOMPtr<nsIInputStream> dataStream;
rv = NS_NewCStringInputStream(getter_AddRefs(dataStream), Move(mQueryString));
NS_ENSURE_SUCCESS(rv, rv);
@ -317,8 +314,6 @@ FSURLEncoded::GetEncodedSubmission(nsIURI* aURI,
mimeStream->SetData(dataStream);
mimeStream.forget(aPostDataStream);
*aPostDataStreamLength = queryStringLength;
}
} else {
@ -626,7 +621,6 @@ FSMultipartFormData::AddDataChunk(const nsACString& aName,
nsresult
FSMultipartFormData::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream,
int64_t* aPostDataStreamLength,
nsCOMPtr<nsIURI>& aOutURI)
{
nsresult rv;
@ -643,7 +637,6 @@ FSMultipartFormData::GetEncodedSubmission(nsIURI* aURI,
uint64_t bodySize;
mimeStream->SetData(GetSubmissionBody(&bodySize));
*aPostDataStreamLength = bodySize;
mimeStream.forget(aPostDataStream);
@ -693,7 +686,7 @@ public:
virtual nsresult
GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
int64_t* aPostDataStreaLength, nsCOMPtr<nsIURI>& aOutURI) override;
nsCOMPtr<nsIURI>& aOutURI) override;
private:
nsString mBody;
@ -733,14 +726,12 @@ FSTextPlain::AddNameDirectoryPair(const nsAString& aName,
nsresult
FSTextPlain::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream,
int64_t* aPostDataStreamLength,
nsCOMPtr<nsIURI>& aOutURI)
{
nsresult rv = NS_OK;
aOutURI = aURI;
*aPostDataStream = nullptr;
*aPostDataStreamLength = -1;
// XXX HACK We are using the standard URL mechanism to give the body to the
// mailer instead of passing the post data stream to it, since that sounds
@ -779,7 +770,6 @@ FSTextPlain::GetEncodedSubmission(nsIURI* aURI,
ConvertLineBreaks(cbody.get(),
nsLinebreakConverter::eLinebreakAny,
nsLinebreakConverter::eLinebreakNet));
uint32_t bodyLength = cbody.Length();
nsCOMPtr<nsIInputStream> bodyStream;
rv = NS_NewCStringInputStream(getter_AddRefs(bodyStream), Move(cbody));
if (!bodyStream) {
@ -794,8 +784,6 @@ FSTextPlain::GetEncodedSubmission(nsIURI* aURI,
mimeStream->AddHeader("Content-Type", "text/plain");
mimeStream->SetData(bodyStream);
CallQueryInterface(mimeStream, aPostDataStream);
*aPostDataStreamLength = bodyLength;
}
return rv;

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

@ -84,12 +84,10 @@ public:
*
* @param aURI the URI being submitted to [IN]
* @param aPostDataStream a data stream for POST data [OUT]
* @param aPostDataStreamLength a data stream for POST data length [OUT]
* @param aOutURI the resulting URI. May be the same as aURI [OUT]
*/
virtual nsresult
GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
int64_t* aPostDataStreamLength,
nsCOMPtr<nsIURI>& aOutURI) = 0;
/**
@ -170,7 +168,7 @@ public:
virtual nsresult
GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
int64_t* aPostDataStreamLength, nsCOMPtr<nsIURI>& aOutURI) override;
nsCOMPtr<nsIURI>& aOutURI) override;
void GetContentType(nsACString& aContentType)
{

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

@ -485,7 +485,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
}
rv = lh->OnLinkClick(content, uri, unitarget.get(), VoidString(),
aPostStream, -1, headersDataStream,
aPostStream, headersDataStream,
/* isUserTriggered */ false,
/* isTrusted */ true, triggeringPrincipal);

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

@ -59,6 +59,7 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/Move.h"
#include "mozilla/net/PartiallySeekableInputStream.h"
#include "mozilla/InputStreamLengthHelper.h"
#include "nsIHttpHeaderVisitor.h"
#include "nsIMIMEInputStream.h"
#include "nsIXULRuntime.h"
@ -188,6 +189,7 @@ HttpBaseChannel::HttpBaseChannel()
, mBlockAuthPrompt(false)
, mAllowStaleCacheContent(false)
, mAddedAsNonTailRequest(false)
, mAsyncOpenWaitingForStreamLength(false)
, mTlsFlags(0)
, mSuspendCount(0)
, mInitialRwin(0)
@ -219,7 +221,7 @@ HttpBaseChannel::HttpBaseChannel()
, mIsTrackingResource(false)
, mLastRedirectFlags(0)
, mReqContentLength(0U)
, mReqContentLengthDetermined(false)
, mPendingInputStreamLengthOperation(false)
{
LOG(("Creating HttpBaseChannel @%p\n", this));
@ -1011,12 +1013,7 @@ HttpBaseChannel::CloneUploadStream(int64_t* aContentLength,
clonedStream.forget(aClonedStream);
if (mReqContentLengthDetermined) {
*aContentLength = mReqContentLength;
} else {
*aContentLength = -1;
}
*aContentLength = mReqContentLength;
return NS_OK;
}
@ -1042,48 +1039,81 @@ HttpBaseChannel::ExplicitSetUploadStream(nsIInputStream *aStream,
"nsIMIMEInputStream should not include headers");
}
if (aContentLength < 0 && !aStreamHasHeaders) {
nsresult rv = aStream->Available(reinterpret_cast<uint64_t*>(&aContentLength));
if (NS_FAILED(rv) || aContentLength < 0) {
NS_ERROR("unable to determine content length");
return NS_ERROR_FAILURE;
}
}
nsresult rv = SetRequestMethod(aMethod);
NS_ENSURE_SUCCESS(rv, rv);
if (!aStreamHasHeaders) {
// SetRequestHeader propagates headers to chrome if HttpChannelChild
nsAutoCString contentLengthStr;
contentLengthStr.AppendInt(aContentLength);
SetRequestHeader(NS_LITERAL_CSTRING("Content-Length"), contentLengthStr,
false);
if (!aContentType.IsVoid()) {
if (aContentType.IsEmpty()) {
SetEmptyRequestHeader(NS_LITERAL_CSTRING("Content-Type"));
} else {
SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"), aContentType,
false);
}
if (!aStreamHasHeaders && !aContentType.IsVoid()) {
if (aContentType.IsEmpty()) {
SetEmptyRequestHeader(NS_LITERAL_CSTRING("Content-Type"));
} else {
SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"), aContentType,
false);
}
}
mUploadStreamHasHeaders = aStreamHasHeaders;
// We already have the content length. We don't need to determinate it.
if (aContentLength > 0) {
mReqContentLength = aContentLength;
mReqContentLengthDetermined = true;
}
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(aStream);
if (!seekable) {
nsCOMPtr<nsIInputStream> stream = aStream;
aStream = new PartiallySeekableInputStream(stream.forget());
seekable = new PartiallySeekableInputStream(stream.forget());
}
mUploadStream = aStream;
mUploadStream = do_QueryInterface(seekable);
if (aContentLength >= 0) {
ExplicitSetUploadStreamLength(aContentLength, aStreamHasHeaders);
return NS_OK;
}
// Sync access to the stream length.
int64_t length;
if (InputStreamLengthHelper::GetSyncLength(aStream, &length)) {
ExplicitSetUploadStreamLength(length >= 0 ? length : 0,
aStreamHasHeaders);
return NS_OK;
}
// Let's resolve the size of the stream.
RefPtr<HttpBaseChannel> self = this;
InputStreamLengthHelper::GetAsyncLength(aStream,
[self, aStreamHasHeaders](int64_t aLength) {
self->mPendingInputStreamLengthOperation = false;
self->ExplicitSetUploadStreamLength(aLength >= 0 ? aLength : 0,
aStreamHasHeaders);
self->MaybeResumeAsyncOpen();
});
mPendingInputStreamLengthOperation = true;
return NS_OK;
}
nsresult
HttpBaseChannel::ExplicitSetUploadStreamLength(uint64_t aContentLength,
bool aStreamHasHeaders)
{
// We already have the content length. We don't need to determinate it.
mReqContentLength = aContentLength;
if (aStreamHasHeaders) {
return NS_OK;
}
nsAutoCString header;
header.AssignLiteral("Content-Length");
// Maybe the content-length header has been already set.
nsAutoCString value;
nsresult rv = GetRequestHeader(header, value);
if (NS_SUCCEEDED(rv) && !value.IsEmpty()) {
return NS_OK;
}
// SetRequestHeader propagates headers to chrome if HttpChannelChild
MOZ_ASSERT(!mWasOpened);
nsAutoCString contentLengthStr;
contentLengthStr.AppendInt(aContentLength);
SetRequestHeader(header, contentLengthStr, false);
return NS_OK;
}
@ -1096,6 +1126,47 @@ HttpBaseChannel::GetUploadStreamHasHeaders(bool *hasHeaders)
return NS_OK;
}
bool
HttpBaseChannel::MaybeWaitForUploadStreamLength(nsIStreamListener *aListener,
nsISupports *aContext)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mAsyncOpenWaitingForStreamLength, "AsyncOpen() called twice?");
if (!mPendingInputStreamLengthOperation) {
return false;
}
mListener = aListener;
mListenerContext = aContext;
mAsyncOpenWaitingForStreamLength = true;
return true;
}
void
HttpBaseChannel::MaybeResumeAsyncOpen()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mPendingInputStreamLengthOperation);
if (!mAsyncOpenWaitingForStreamLength) {
return;
}
nsCOMPtr<nsIStreamListener> listener;
listener.swap(mListener);
nsCOMPtr<nsISupports> context;
context.swap(mListenerContext);
mAsyncOpenWaitingForStreamLength = false;
nsresult rv = AsyncOpen(listener, context);
if (NS_WARN_IF(NS_FAILED(rv))) {
DoAsyncAbort(rv);
}
}
//-----------------------------------------------------------------------------
// HttpBaseChannel::nsIEncodedChannel
//-----------------------------------------------------------------------------

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

@ -387,6 +387,11 @@ public: /* Necko internal use only... */
mUploadStream = uploadStream;
}
void InternalSetUploadStreamLength(uint64_t aLength)
{
mReqContentLength = aLength;
}
void SetUploadStreamHasHeaders(bool hasHeaders)
{
mUploadStreamHasHeaders = hasHeaders;
@ -420,6 +425,10 @@ protected:
// drop reference to listener, its callbacks, and the progress sink
virtual void ReleaseListeners();
// Call AsyncAbort().
virtual void
DoAsyncAbort(nsresult aStatus) = 0;
// This is fired only when a cookie is created due to the presence of
// Set-Cookie header in the response header of any network request.
// This notification will come only after the "http-on-examine-response"
@ -482,6 +491,10 @@ protected:
nsresult
CheckRedirectLimit(uint32_t aRedirectFlags) const;
bool
MaybeWaitForUploadStreamLength(nsIStreamListener *aListener,
nsISupports *aContext);
friend class PrivateBrowsingChannel<HttpBaseChannel>;
friend class InterceptFailedOnStop;
@ -512,6 +525,13 @@ private:
bool IsCrossOriginWithReferrer();
nsresult
ExplicitSetUploadStreamLength(uint64_t aContentLength,
bool aStreamHasHeaders);
void
MaybeResumeAsyncOpen();
protected:
// Use Release-Acquire ordering to ensure the OMT ODA is ignored while channel
// is canceled on main thread.
@ -598,6 +618,11 @@ protected:
// a non tail request. We must remove it again when this channel is done.
uint32_t mAddedAsNonTailRequest : 1;
// True if AsyncOpen() is called when the stream length is still unknown.
// AsyncOpen() will be retriggered when InputStreamLengthHelper execs the
// callback, passing the stream length value.
uint32_t mAsyncOpenWaitingForStreamLength : 1;
// An opaque flags for non-standard behavior of the TLS system.
// It is unlikely this will need to be set outside of telemetry studies
// relating to the TLS implementation.
@ -716,7 +741,6 @@ protected:
uint32_t mLastRedirectFlags;
uint64_t mReqContentLength;
bool mReqContentLengthDetermined;
nsString mIntegrityMetadata;
@ -724,6 +748,10 @@ protected:
nsCString mMatchedList;
nsCString mMatchedProvider;
nsCString mMatchedFullHash;
// This is set true if the channel is waiting for the
// InputStreamLengthHelper::GetAsyncLength callback.
bool mPendingInputStreamLengthOperation;
};
NS_DEFINE_STATIC_IID_ACCESSOR(HttpBaseChannel, HTTP_BASE_CHANNEL_IID)

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

@ -1511,6 +1511,12 @@ HttpChannelChild::DoNotifyListenerCleanup()
MaybeCallSynthesizedCallback();
}
void
HttpChannelChild::DoAsyncAbort(nsresult aStatus)
{
Unused << AsyncAbort(aStatus);
}
class DeleteSelfEvent : public NeckoTargetChannelEvent<HttpChannelChild>
{
public:
@ -2486,6 +2492,10 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
if (MaybeWaitForUploadStreamLength(listener, aContext)) {
return NS_OK;
}
mAsyncOpenTime = TimeStamp::Now();
#ifdef MOZ_TASK_TRACER
if (tasktracer::IsStartLogging()) {

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

@ -181,6 +181,8 @@ protected:
GetAssociatedContentSecurity(nsIAssociatedContentSecurity** res = nullptr);
virtual void DoNotifyListenerCleanup() override;
virtual void DoAsyncAbort(nsresult aStatus) override;
NS_IMETHOD GetResponseSynthesized(bool* aSynthesized) override;
nsresult

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

@ -15,6 +15,7 @@
#include "mozilla/dom/ServiceWorkerUtils.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/net/NeckoParent.h"
#include "mozilla/InputStreamLengthHelper.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
@ -401,47 +402,6 @@ HttpChannelParent::InvokeAsyncOpen(nsresult rv)
}
}
namespace {
class InvokeAsyncOpen : public Runnable
{
nsMainThreadPtrHandle<nsIInterfaceRequestor> mChannel;
nsresult mStatus;
public:
InvokeAsyncOpen(const nsMainThreadPtrHandle<nsIInterfaceRequestor>& aChannel,
nsresult aStatus)
: Runnable("net::InvokeAsyncOpen")
, mChannel(aChannel)
, mStatus(aStatus)
{
}
NS_IMETHOD Run() override
{
RefPtr<HttpChannelParent> channel = do_QueryObject(mChannel.get());
channel->TryInvokeAsyncOpen(mStatus);
return NS_OK;
}
};
struct UploadStreamClosure {
nsMainThreadPtrHandle<nsIInterfaceRequestor> mChannel;
explicit UploadStreamClosure(const nsMainThreadPtrHandle<nsIInterfaceRequestor>& aChannel)
: mChannel(aChannel)
{
}
};
void
UploadCopyComplete(void* aClosure, nsresult aStatus) {
// Called on the Stream Transport Service thread by NS_AsyncCopy
MOZ_ASSERT(!NS_IsMainThread());
UniquePtr<UploadStreamClosure> closure(static_cast<UploadStreamClosure*>(aClosure));
nsCOMPtr<nsIRunnable> event = new InvokeAsyncOpen(closure->mChannel, aStatus);
NS_DispatchToMainThread(event);
}
} // anonymous namespace
bool
HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
const OptionalURIParams& aOriginalURI,
@ -602,62 +562,24 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(uploadStream);
if (stream) {
// FIXME: The fast path of using the existing stream currently only applies to streams
// that have had their entire contents serialized from the child at this point.
// Once bug 1294446 and bug 1294450 are fixed it is worth revisiting this heuristic.
nsCOMPtr<nsIIPCSerializableInputStream> completeStream = do_QueryInterface(stream);
if (!completeStream) {
// Wait for completion of async copying IPC upload stream to a local input stream.
int64_t length;
if (InputStreamLengthHelper::GetSyncLength(stream, &length)) {
httpChannel->InternalSetUploadStreamLength(length >= 0 ? length : 0);
} else {
// Wait for the nputStreamLengthHelper::GetAsyncLength callback.
++mAsyncOpenBarrier;
// buffer size matches PChildToParentStream transfer size.
const uint32_t kBufferSize = 32768;
nsCOMPtr<nsIStorageStream> storageStream;
nsresult rv = NS_NewStorageStream(kBufferSize, UINT32_MAX,
getter_AddRefs(storageStream));
if (NS_WARN_IF(NS_FAILED(rv))) {
return SendFailedAsyncOpen(rv);
}
nsCOMPtr<nsIInputStream> newUploadStream;
rv = storageStream->NewInputStream(0, getter_AddRefs(newUploadStream));
if (NS_WARN_IF(NS_FAILED(rv))) {
return SendFailedAsyncOpen(rv);
}
nsCOMPtr<nsIOutputStream> sink;
rv = storageStream->GetOutputStream(0, getter_AddRefs(sink));
if (NS_WARN_IF(NS_FAILED(rv))) {
return SendFailedAsyncOpen(rv);
}
nsCOMPtr<nsIEventTarget> target =
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv) || !target) {
return SendFailedAsyncOpen(rv);
}
nsCOMPtr<nsIInterfaceRequestor> iir = static_cast<nsIInterfaceRequestor*>(this);
nsMainThreadPtrHandle<nsIInterfaceRequestor> handle =
nsMainThreadPtrHandle<nsIInterfaceRequestor>(
new nsMainThreadPtrHolder<nsIInterfaceRequestor>(
"nsIInterfaceRequestor", iir));
UniquePtr<UploadStreamClosure> closure(new UploadStreamClosure(handle));
// Accumulate the stream contents as the child sends it. We will continue with
// the AsyncOpen process once the full stream has been received.
rv = NS_AsyncCopy(stream, sink, target, NS_ASYNCCOPY_VIA_READSEGMENTS,
kBufferSize, // copy segment size
UploadCopyComplete, closure.release());
if (NS_WARN_IF(NS_FAILED(rv))) {
return SendFailedAsyncOpen(rv);
}
httpChannel->InternalSetUploadStream(newUploadStream);
} else {
httpChannel->InternalSetUploadStream(stream);
// Let's resolve the size of the stream. The following operation is always
// async.
RefPtr<HttpChannelParent> self = this;
InputStreamLengthHelper::GetAsyncLength(stream,
[self, httpChannel](int64_t aLength) {
httpChannel->InternalSetUploadStreamLength(aLength >= 0 ? aLength : 0);
self->TryInvokeAsyncOpen(NS_OK);
});
}
httpChannel->InternalSetUploadStream(stream);
httpChannel->SetUploadStreamHasHeaders(uploadStreamHasHeaders);
}

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

@ -650,6 +650,12 @@ InterceptedHttpChannel::DoNotifyListenerCleanup()
// more consistently in necko.
}
void
InterceptedHttpChannel::DoAsyncAbort(nsresult aStatus)
{
Unused << AsyncAbort(aStatus);
}
NS_IMETHODIMP
InterceptedHttpChannel::ResetInterception(void)

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

@ -193,6 +193,9 @@ public:
void
DoNotifyListenerCleanup() override;
void
DoAsyncAbort(nsresult aStatus) override;
};
} // namespace net

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

@ -638,73 +638,9 @@ nsHttpChannel::ConnectOnTailUnblock()
return TriggerNetwork();
}
// nsIInputAvailableCallback (nsIStreamTransportService.idl)
NS_IMETHODIMP
nsHttpChannel::OnInputAvailableComplete(uint64_t size, nsresult status)
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread.");
LOG(("nsHttpChannel::OnInputAvailableComplete %p %" PRIx32 "\n",
this, static_cast<uint32_t>(status)));
if (NS_SUCCEEDED(status)) {
mReqContentLength = size;
} else {
// fall back to synchronous on the error path. should not happen.
if (NS_SUCCEEDED(mUploadStream->Available(&size))) {
mReqContentLength = size;
}
}
LOG(("nsHttpChannel::DetermineContentLength %p from sts\n", this));
mReqContentLengthDetermined = true;
nsresult rv = mCanceled ? mStatus : ContinueConnect();
if (NS_FAILED(rv)) {
CloseCacheEntry(false);
Unused << AsyncAbort(rv);
}
return NS_OK;
}
void
nsHttpChannel::DetermineContentLength()
{
nsCOMPtr<nsIStreamTransportService> sts(services::GetStreamTransportService());
if (!mUploadStream || !sts) {
LOG(("nsHttpChannel::DetermineContentLength %p no body\n", this));
mReqContentLength = 0U;
mReqContentLengthDetermined = true;
return;
}
// If this is a stream is blocking, it needs to be sent to a worker thread
// to do Available() as it may cause disk/IO.
bool nonBlocking = false;
if (NS_FAILED(mUploadStream->IsNonBlocking(&nonBlocking)) || nonBlocking) {
mUploadStream->Available(&mReqContentLength);
LOG(("nsHttpChannel::DetermineContentLength %p from mem\n", this));
mReqContentLengthDetermined = true;
return;
}
LOG(("nsHttpChannel::DetermineContentLength Async [this=%p]\n", this));
sts->InputAvailable(mUploadStream, this);
}
nsresult
nsHttpChannel::ContinueConnect()
{
// If we have a request body that is going to require bouncing to the STS
// in order to determine the content-length as doing it on the main thread
// will incur file IO some of the time.
if (!mReqContentLengthDetermined) {
// C-L might be determined sync or async. Sync will set
// mReqContentLengthDetermined to true in DetermineContentLength()
DetermineContentLength();
}
if (!mReqContentLengthDetermined) {
return NS_OK;
}
// If we need to start a CORS preflight, do it now!
// Note that it is important to do this before the early returns below.
if (!mIsCorsPreflightDone && mRequireCORSPreflight) {
@ -834,6 +770,12 @@ nsHttpChannel::ReleaseListeners()
mWarningReporter = nullptr;
}
void
nsHttpChannel::DoAsyncAbort(nsresult aStatus)
{
Unused << AsyncAbort(aStatus);
}
void
nsHttpChannel::HandleAsyncRedirect()
{
@ -5837,7 +5779,6 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)
NS_INTERFACE_MAP_ENTRY(nsIInputAvailableCallback)
NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
NS_INTERFACE_MAP_ENTRY(nsIHttpAuthenticableChannel)
NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
@ -5989,6 +5930,10 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
if (MaybeWaitForUploadStreamLength(listener, context)) {
return NS_OK;
}
nsresult rv;
MOZ_ASSERT(NS_IsMainThread());

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

@ -73,7 +73,6 @@ class nsHttpChannel final : public HttpBaseChannel
, public nsICacheEntryOpenCallback
, public nsITransportEventSink
, public nsIProtocolProxyCallback
, public nsIInputAvailableCallback
, public nsIHttpAuthenticableChannel
, public nsIApplicationCacheChannel
, public nsIAsyncVerifyRedirectCallback
@ -97,7 +96,6 @@ public:
NS_DECL_NSICACHEENTRYOPENCALLBACK
NS_DECL_NSITRANSPORTEVENTSINK
NS_DECL_NSIPROTOCOLPROXYCALLBACK
NS_DECL_NSIINPUTAVAILABLECALLBACK
NS_DECL_NSIPROXIEDCHANNEL
NS_DECL_NSIAPPLICATIONCACHECONTAINER
NS_DECL_NSIAPPLICATIONCACHECHANNEL
@ -399,8 +397,6 @@ private:
MOZ_MUST_USE nsresult ContinueAsyncRedirectChannelToURI(nsresult rv);
MOZ_MUST_USE nsresult OpenRedirectChannel(nsresult rv);
void DetermineContentLength();
/**
* A function that takes care of reading STS and PKP headers and enforcing
* STS and PKP load rules. After a secure channel is erected, STS and PKP
@ -716,6 +712,8 @@ protected:
// in nsHttpChannel and it will be released in ReleaseListeners().
virtual void ReleaseListeners() override;
virtual void DoAsyncAbort(nsresult aStatus) override;
private: // cache telemetry
bool mDidReval;
};

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

@ -7,12 +7,128 @@
#include "InputStreamLengthHelper.h"
#include "mozilla/dom/WorkerCommon.h"
#include "nsIInputStream.h"
#include "nsIStreamTransportService.h"
static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
namespace mozilla {
namespace {
class AvailableEvent final : public Runnable
{
public:
AvailableEvent(nsIInputStream* stream,
const std::function<void(int64_t aLength)>& aCallback)
: Runnable("mozilla::AvailableEvent")
, mStream(stream)
, mCallback(aCallback)
, mSize(-1)
{
mCallbackTarget = GetCurrentThreadSerialEventTarget();
MOZ_ASSERT(NS_IsMainThread());
}
NS_IMETHOD
Run() override
{
// ping
if (!NS_IsMainThread()) {
uint64_t size = 0;
if (NS_WARN_IF(NS_FAILED(mStream->Available(&size)))) {
mSize = -1;
} else {
mSize = (int64_t)size;
}
mStream = nullptr;
nsCOMPtr<nsIRunnable> self(this); // overly cute
mCallbackTarget->Dispatch(self.forget(), NS_DISPATCH_NORMAL);
mCallbackTarget = nullptr;
return NS_OK;
}
// pong
mCallback(mSize);
return NS_OK;
}
private:
nsCOMPtr<nsIInputStream> mStream;
std::function<void(int64_t aLength)> mCallback;
nsCOMPtr<nsIEventTarget> mCallbackTarget;
int64_t mSize;
};
} // anonymous
/* static */ bool
InputStreamLengthHelper::GetSyncLength(nsIInputStream* aStream,
int64_t* aLength)
{
MOZ_ASSERT(aStream);
MOZ_ASSERT(aLength);
*aLength = -1;
// Sync length access.
nsCOMPtr<nsIInputStreamLength> streamLength = do_QueryInterface(aStream);
if (streamLength) {
int64_t length = -1;
nsresult rv = streamLength->Length(&length);
// All good!
if (NS_SUCCEEDED(rv)) {
*aLength = length;
return true;
}
// Already closed stream or an error occurred.
if (rv == NS_BASE_STREAM_CLOSED ||
NS_WARN_IF(rv == NS_ERROR_NOT_AVAILABLE) ||
NS_WARN_IF(rv != NS_BASE_STREAM_WOULD_BLOCK)) {
return true;
}
}
nsCOMPtr<nsIAsyncInputStreamLength> asyncStreamLength =
do_QueryInterface(aStream);
if (asyncStreamLength) {
// GetAsyncLength should be used.
return false;
}
// For main-thread only, we want to avoid calling ::Available() for blocking
// streams.
if (NS_IsMainThread()) {
bool nonBlocking = false;
if (NS_WARN_IF(NS_FAILED(aStream->IsNonBlocking(&nonBlocking)))) {
// Let's return -1. There is nothing else we can do here.
return true;
}
if (!nonBlocking) {
return false;
}
}
// Fallback using available().
uint64_t available = 0;
nsresult rv = aStream->Available(&available);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Let's return -1. There is nothing else we can do here.
return true;
}
*aLength = (int64_t)available;
return true;
}
/* static */ void
InputStreamLengthHelper::GetLength(nsIInputStream* aStream,
const std::function<void(int64_t aLength)>& aCallback)
InputStreamLengthHelper::GetAsyncLength(nsIInputStream* aStream,
const std::function<void(int64_t aLength)>& aCallback)
{
MOZ_ASSERT(aStream);
MOZ_ASSERT(aCallback);
@ -24,6 +140,25 @@ InputStreamLengthHelper::GetLength(nsIInputStream* aStream,
RefPtr<InputStreamLengthHelper> helper =
new InputStreamLengthHelper(aStream, aCallback);
// Let's be sure that we don't call ::Available() on main-thread.
if (NS_IsMainThread()) {
nsCOMPtr<nsIInputStreamLength> streamLength = do_QueryInterface(aStream);
nsCOMPtr<nsIAsyncInputStreamLength> asyncStreamLength =
do_QueryInterface(aStream);
if (!streamLength && !asyncStreamLength) {
bool nonBlocking = false;
if (NS_SUCCEEDED(aStream->IsNonBlocking(&nonBlocking)) && !nonBlocking) {
nsCOMPtr<nsIEventTarget> target =
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
MOZ_ASSERT(target);
RefPtr<AvailableEvent> event = new AvailableEvent(aStream, aCallback);
target->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
return;
}
}
}
// Let's go async in order to have similar behaviors for sync and async
// nsIInputStreamLength implementations.
GetCurrentThreadSerialEventTarget()->Dispatch(helper, NS_DISPATCH_NORMAL);

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

@ -19,11 +19,17 @@ class InputStreamLengthHelper final : public Runnable
public:
NS_DECL_ISUPPORTS_INHERITED
// This is the entry point of this class. The callback is executed
// This is one of the 2 entry points of this class. It returns false if the
// length cannot be taken synchronously.
static bool
GetSyncLength(nsIInputStream* aStream,
int64_t* aLength);
// This is one of the 2 entry points of this class. The callback is executed
// asynchronously when the length is known.
static void
GetLength(nsIInputStream* aStream,
const std::function<void(int64_t aLength)>& aCallback);
GetAsyncLength(nsIInputStream* aStream,
const std::function<void(int64_t aLength)>& aCallback);
private:
NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK

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

@ -22,7 +22,7 @@ TEST(TestInputStreamLengthHelper, NonLengthStream) {
NS_NewCStringInputStream(getter_AddRefs(stream), buf);
bool called = false;
InputStreamLengthHelper::GetLength(stream, [&](int64_t aLength) {
InputStreamLengthHelper::GetAsyncLength(stream, [&](int64_t aLength) {
ASSERT_EQ(buf.Length(), aLength);
called = true;
});
@ -93,7 +93,7 @@ TEST(TestInputStreamLengthHelper, LengthStream) {
nsCOMPtr<nsIInputStream> stream = new LengthStream(42, NS_OK, 0, false);
bool called = false;
InputStreamLengthHelper::GetLength(stream, [&](int64_t aLength) {
InputStreamLengthHelper::GetAsyncLength(stream, [&](int64_t aLength) {
ASSERT_EQ(42, aLength);
called = true;
});
@ -106,7 +106,7 @@ TEST(TestInputStreamLengthHelper, InvalidLengthStream) {
new LengthStream(42, NS_ERROR_NOT_AVAILABLE, 0, false);
bool called = false;
InputStreamLengthHelper::GetLength(stream, [&](int64_t aLength) {
InputStreamLengthHelper::GetAsyncLength(stream, [&](int64_t aLength) {
ASSERT_EQ(-1, aLength);
called = true;
});
@ -119,7 +119,7 @@ TEST(TestInputStreamLengthHelper, AsyncLengthStream) {
new LengthStream(22, NS_BASE_STREAM_WOULD_BLOCK, 123, true);
bool called = false;
InputStreamLengthHelper::GetLength(stream, [&](int64_t aLength) {
InputStreamLengthHelper::GetAsyncLength(stream, [&](int64_t aLength) {
ASSERT_EQ(22, aLength);
called = true;
});
@ -132,7 +132,7 @@ TEST(TestInputStreamLengthHelper, FallbackLengthStream) {
new LengthStream(-1, NS_BASE_STREAM_WOULD_BLOCK, 123, false);
bool called = false;
InputStreamLengthHelper::GetLength(stream, [&](int64_t aLength) {
InputStreamLengthHelper::GetAsyncLength(stream, [&](int64_t aLength) {
ASSERT_EQ(123, aLength);
called = true;
});