зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1847358 part 2: create and use nsIBaseChannel to reduce code debt and better-encapsulate logic for range-requests on nsBaseChannel classes; r=dlrobertson,necko-reviewers,jesup
Differential Revision: https://phabricator.services.mozilla.com/D203379
This commit is contained in:
Родитель
820f1c6cb8
Коммит
7c31f0e0ae
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/dom/ReferrerInfo.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "nsIBaseChannel.h"
|
||||
#include "nsICookieJarSettings.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIInputStream.h"
|
||||
|
@ -28,7 +29,6 @@
|
|||
#include "nsIPipe.h"
|
||||
#include "nsIRedirectHistoryEntry.h"
|
||||
|
||||
#include "nsBaseChannel.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsDataChannel.h"
|
||||
#include "nsDataHandler.h"
|
||||
|
@ -1100,13 +1100,10 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest) {
|
|||
// Should set a Content-Range header for blob scheme
|
||||
// (https://fetch.spec.whatwg.org/#scheme-fetch)
|
||||
nsAutoCString contentRange(VoidCString());
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
channel->GetURI(getter_AddRefs(uri));
|
||||
if (IsBlobURI(uri)) {
|
||||
nsBaseChannel* bchan = static_cast<nsBaseChannel*>(channel.get());
|
||||
MOZ_ASSERT(bchan);
|
||||
Maybe<mozilla::net::ContentRange> range = bchan->GetContentRange();
|
||||
if (range.isSome()) {
|
||||
nsCOMPtr<nsIBaseChannel> baseChan = do_QueryInterface(mChannel);
|
||||
if (baseChan) {
|
||||
RefPtr<mozilla::net::ContentRange> range = baseChan->ContentRange();
|
||||
if (range) {
|
||||
range->AsHeader(contentRange);
|
||||
}
|
||||
}
|
||||
|
@ -1122,6 +1119,8 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest) {
|
|||
MOZ_ASSERT(!result.Failed());
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
channel->GetURI(getter_AddRefs(uri));
|
||||
if (uri && uri->SchemeIs("data")) {
|
||||
nsDataChannel* dchan = static_cast<nsDataChannel*>(channel.get());
|
||||
MOZ_ASSERT(dchan);
|
||||
|
|
|
@ -489,9 +489,9 @@ nsresult BlobURLInputStream::StoreBlobImplStream(
|
|||
// If a Range header was in the request then fetch/XHR will have set a
|
||||
// ContentRange on the channel earlier so we may slice the blob now.
|
||||
blobImpl->GetType(blobContentType);
|
||||
const Maybe<mozilla::net::ContentRange>& contentRange =
|
||||
mChannel->GetContentRange();
|
||||
if (contentRange.isSome()) {
|
||||
const RefPtr<mozilla::net::ContentRange>& contentRange =
|
||||
mChannel->ContentRange();
|
||||
if (contentRange) {
|
||||
IgnoredErrorResult result;
|
||||
uint64_t start = contentRange->Start();
|
||||
uint64_t end = contentRange->End();
|
||||
|
|
|
@ -948,7 +948,7 @@ nsresult NS_GetBlobForBlobURISpec(const nsACString& aSpec,
|
|||
}
|
||||
|
||||
// Blob requests may specify a range header. We parse, validate, and
|
||||
// store that info here, and save it on the nsBaseChannel, where it
|
||||
// store that info here, and save it on the nsIBaseChannel, where it
|
||||
// can be accessed by BlobURLInputStream::StoreBlobImplStream.
|
||||
nsresult NS_SetChannelContentRangeForBlobURI(nsIChannel* aChannel, nsIURI* aURI,
|
||||
nsACString& aRangeHeader) {
|
||||
|
@ -963,9 +963,8 @@ nsresult NS_SetChannelContentRangeForBlobURI(nsIChannel* aChannel, nsIURI* aURI,
|
|||
if (result.Failed()) {
|
||||
return NS_ERROR_NO_CONTENT;
|
||||
}
|
||||
nsBaseChannel* bchan = static_cast<nsBaseChannel*>(aChannel);
|
||||
MOZ_ASSERT(bchan);
|
||||
if (!bchan->SetContentRange(aRangeHeader, size)) {
|
||||
nsCOMPtr<nsIBaseChannel> baseChan = do_QueryInterface(aChannel);
|
||||
if (!baseChan || !baseChan->SetContentRangeFromHeader(aRangeHeader, size)) {
|
||||
return NS_ERROR_NET_PARTIAL_TRANSFER;
|
||||
}
|
||||
return NS_OK;
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "mozilla/StaticPrefs_privacy.h"
|
||||
#include "mozilla/dom/ProgressEvent.h"
|
||||
#include "nsDataChannel.h"
|
||||
#include "nsIBaseChannel.h"
|
||||
#include "nsIJARChannel.h"
|
||||
#include "nsIJARURI.h"
|
||||
#include "nsReadableUtils.h"
|
||||
|
@ -864,14 +865,28 @@ bool XMLHttpRequestMainThread::IsDeniedCrossSiteCORSRequest() {
|
|||
return false;
|
||||
}
|
||||
|
||||
Maybe<mozilla::net::ContentRange>
|
||||
bool XMLHttpRequestMainThread::BadContentRangeRequested() {
|
||||
if (!mChannel) {
|
||||
return false;
|
||||
}
|
||||
// Only nsIBaseChannel supports this
|
||||
nsCOMPtr<nsIBaseChannel> baseChan = do_QueryInterface(mChannel);
|
||||
if (!baseChan) {
|
||||
return false;
|
||||
}
|
||||
// A bad range was requested if the channel has no content range
|
||||
// despite the request specifying a range header.
|
||||
return !baseChan->ContentRange() && mAuthorRequestHeaders.Has("range");
|
||||
}
|
||||
|
||||
RefPtr<mozilla::net::ContentRange>
|
||||
XMLHttpRequestMainThread::GetRequestedContentRange() const {
|
||||
MOZ_ASSERT(mChannel);
|
||||
nsBaseChannel* baseChan = static_cast<nsBaseChannel*>(mChannel.get());
|
||||
nsCOMPtr<nsIBaseChannel> baseChan = do_QueryInterface(mChannel);
|
||||
if (!baseChan) {
|
||||
return mozilla::Nothing();
|
||||
return nullptr;
|
||||
}
|
||||
return baseChan->GetContentRange();
|
||||
return baseChan->ContentRange();
|
||||
}
|
||||
|
||||
void XMLHttpRequestMainThread::GetContentRangeHeader(nsACString& out) const {
|
||||
|
@ -879,8 +894,8 @@ void XMLHttpRequestMainThread::GetContentRangeHeader(nsACString& out) const {
|
|||
out.SetIsVoid(true);
|
||||
return;
|
||||
}
|
||||
Maybe<mozilla::net::ContentRange> range = GetRequestedContentRange();
|
||||
if (range.isSome()) {
|
||||
RefPtr<mozilla::net::ContentRange> range = GetRequestedContentRange();
|
||||
if (range) {
|
||||
range->AsHeader(out);
|
||||
} else {
|
||||
out.SetIsVoid(true);
|
||||
|
@ -944,8 +959,7 @@ uint32_t XMLHttpRequestMainThread::GetStatus(ErrorResult& aRv) {
|
|||
nsCOMPtr<nsIHttpChannel> httpChannel = GetCurrentHttpChannel();
|
||||
if (!httpChannel) {
|
||||
// Pretend like we got a 200/206 response, since our load was successful
|
||||
return IsBlobURI(mRequestURL) && GetRequestedContentRange().isSome() ? 206
|
||||
: 200;
|
||||
return GetRequestedContentRange() ? 206 : 200;
|
||||
}
|
||||
|
||||
uint32_t status;
|
||||
|
@ -1956,8 +1970,7 @@ XMLHttpRequestMainThread::OnStartRequest(nsIRequest* request) {
|
|||
|
||||
// If we were asked for a bad range on a blob URL, but we're async,
|
||||
// we should throw now in order to fire an error progress event.
|
||||
if (IsBlobURI(mRequestURL) && GetRequestedContentRange().isNothing() &&
|
||||
mAuthorRequestHeaders.Has("range")) {
|
||||
if (BadContentRangeRequested()) {
|
||||
return NS_ERROR_NET_PARTIAL_TRANSFER;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
#include "mozilla/dom/XMLHttpRequestEventTarget.h"
|
||||
#include "mozilla/dom/XMLHttpRequestString.h"
|
||||
#include "mozilla/Encoding.h"
|
||||
#include "nsBaseChannel.h"
|
||||
|
||||
#ifdef Status
|
||||
/* Xlib headers insist on this for some reason... Nuke it because
|
||||
|
@ -65,6 +64,10 @@ class nsILoadGroup;
|
|||
namespace mozilla {
|
||||
class ProfileChunkedBuffer;
|
||||
|
||||
namespace net {
|
||||
class ContentRange;
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
|
||||
class DOMString;
|
||||
|
@ -507,7 +510,8 @@ class XMLHttpRequestMainThread final : public XMLHttpRequest,
|
|||
|
||||
void AbortInternal(ErrorResult& aRv);
|
||||
|
||||
Maybe<mozilla::net::ContentRange> GetRequestedContentRange() const;
|
||||
bool BadContentRangeRequested();
|
||||
RefPtr<mozilla::net::ContentRange> GetRequestedContentRange() const;
|
||||
void GetContentRangeHeader(nsACString&) const;
|
||||
|
||||
struct PendingEvent {
|
||||
|
|
|
@ -21,6 +21,8 @@ namespace mozilla::net {
|
|||
|
||||
class ContentRange {
|
||||
private:
|
||||
~ContentRange() = default;
|
||||
|
||||
uint64_t mStart{0};
|
||||
uint64_t mEnd{0};
|
||||
uint64_t mSize{0};
|
||||
|
@ -34,6 +36,8 @@ class ContentRange {
|
|||
: mStart(aStart), mEnd(aEnd), mSize(aSize) {}
|
||||
ContentRange(const nsACString& aRangeHeader, uint64_t aSize);
|
||||
void AsHeader(nsACString& aOutString) const;
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(ContentRange)
|
||||
};
|
||||
|
||||
} // namespace mozilla::net
|
||||
|
|
|
@ -18,6 +18,7 @@ XPIDL_SOURCES += [
|
|||
"nsIAuthPromptCallback.idl",
|
||||
"nsIAuthPromptProvider.idl",
|
||||
"nsIBackgroundFileSaver.idl",
|
||||
"nsIBaseChannel.idl",
|
||||
"nsIBufferedStreams.idl",
|
||||
"nsIByteRangeRequest.idl",
|
||||
"nsICacheInfoChannel.idl",
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsURLHelper.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsUnknownDecoder.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsMimeTypes.h"
|
||||
|
@ -302,6 +301,7 @@ NS_IMPL_RELEASE(nsBaseChannel)
|
|||
NS_INTERFACE_MAP_BEGIN(nsBaseChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRequest)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIBaseChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
|
||||
|
@ -966,3 +966,17 @@ NS_IMETHODIMP nsBaseChannel::GetCanceled(bool* aCanceled) {
|
|||
void nsBaseChannel::SetupNeckoTarget() {
|
||||
mNeckoTarget = GetMainThreadSerialEventTarget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsBaseChannel::GetContentRange(
|
||||
RefPtr<mozilla::net::ContentRange>* aRange) {
|
||||
if (aRange) {
|
||||
*aRange = mContentRange;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsBaseChannel::SetContentRange(
|
||||
RefPtr<mozilla::net::ContentRange> aRange) {
|
||||
mContentRange = aRange;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "mozilla/net/PrivateBrowsingChannel.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsIBaseChannel.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsILoadGroup.h"
|
||||
|
@ -47,6 +48,7 @@ class nsICancelable;
|
|||
|
||||
class nsBaseChannel
|
||||
: public nsHashPropertyBag,
|
||||
public nsIBaseChannel,
|
||||
public nsIChannel,
|
||||
public nsIThreadRetargetableRequest,
|
||||
public nsIInterfaceRequestor,
|
||||
|
@ -59,6 +61,7 @@ class nsBaseChannel
|
|||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIREQUEST
|
||||
NS_DECL_NSICHANNEL
|
||||
NS_DECL_NSIBASECHANNEL
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSITRANSPORTEVENTSINK
|
||||
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
|
||||
|
@ -198,26 +201,6 @@ class nsBaseChannel
|
|||
return mPumpingData || mWaitingOnAsyncRedirect;
|
||||
}
|
||||
|
||||
// Blob requests may specify a range header. We must parse, validate, and
|
||||
// store that info in a place where BlobURLInputStream::StoreBlobImplStream
|
||||
// can access it.
|
||||
const mozilla::Maybe<mozilla::net::ContentRange>& GetContentRange() const {
|
||||
return mContentRange;
|
||||
}
|
||||
|
||||
void SetContentRange(uint64_t aStart, uint64_t aEnd, uint64_t aSize) {
|
||||
mContentRange.emplace(mozilla::net::ContentRange(aStart, aEnd, aSize));
|
||||
}
|
||||
|
||||
bool SetContentRange(const nsACString& aRangeHeader, uint64_t aSize) {
|
||||
auto range = mozilla::net::ContentRange(aRangeHeader, aSize);
|
||||
if (!range.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
mContentRange.emplace(range);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper function for querying the channel's notification callbacks.
|
||||
template <class T>
|
||||
void GetCallback(nsCOMPtr<T>& result) {
|
||||
|
@ -308,7 +291,7 @@ class nsBaseChannel
|
|||
bool mWaitingOnAsyncRedirect{false};
|
||||
bool mOpenRedirectChannel{false};
|
||||
uint32_t mRedirectFlags{0};
|
||||
mozilla::Maybe<mozilla::net::ContentRange> mContentRange;
|
||||
RefPtr<mozilla::net::ContentRange> mContentRange;
|
||||
|
||||
protected:
|
||||
nsCString mContentType;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
%{C++
|
||||
#include "mozilla/net/ContentRange.h"
|
||||
%}
|
||||
|
||||
/**
|
||||
* The nsIBaseChannel interface allows C++ code to query the interface
|
||||
* of channels safely to gain access to content range functionality.
|
||||
* This allows subclasses to optionally handle range-requests on their
|
||||
* types using fetch/XMLHttpRequest even if they are not accessed via
|
||||
* HTTP and therefore normally do not have support for headers.
|
||||
*/
|
||||
|
||||
native ContentRangeRef(RefPtr<mozilla::net::ContentRange>);
|
||||
|
||||
[uuid(036d5cd7-9a53-40e3-9c72-c2ffaa15aa2b)]
|
||||
interface nsIBaseChannel : nsISupports {
|
||||
|
||||
/**
|
||||
* Used by fetch and XMLHttpRequest to get only the range specified in the
|
||||
* Range request header (if given) for the response body (e.g, for blob URLs)
|
||||
*/
|
||||
attribute ContentRangeRef contentRange;
|
||||
|
||||
%{C++
|
||||
RefPtr<mozilla::net::ContentRange> ContentRange() {
|
||||
RefPtr<mozilla::net::ContentRange> range;
|
||||
mozilla::Unused << GetContentRange(&range);
|
||||
return range;
|
||||
}
|
||||
|
||||
bool SetContentRangeFromHeader(const nsACString& aHeader, uint64_t aSize) {
|
||||
RefPtr<mozilla::net::ContentRange> range =
|
||||
new mozilla::net::ContentRange(aHeader, aSize);
|
||||
if (!range->IsValid()) {
|
||||
return false;
|
||||
}
|
||||
SetContentRange(range);
|
||||
return true;
|
||||
}
|
||||
%}
|
||||
|
||||
};
|
Загрузка…
Ссылка в новой задаче