зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1434553 - Implement nsIInputStreamLength and nsIAsyncInputStreamLength - part 9 - necko and docShell, r=mayhemer, r=smaug
This commit is contained in:
Родитель
4d342e4ebf
Коммит
7dcc1b6880
|
@ -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;
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче