ported from UXP:

- Allow matroska and avc (h.264) content in matroska/webm containers for video element and MSE. (18f9b185)
- Alow AAC audio codec data in matroska/webm streams. Allow CRC32 elements in matroska cluster elements. (6b6aa59f)
- Truncate Buffer/Texture on GL_OOM. (3f9e299b)
- Bug 1550498 (b0a8ed21)
- Don't allow cross-origin POST redirects on 308 codes. (8b7daa53)
- Bug 1548822 (b7807cd0)
- Do not allow the ^ character to appear in the hostname. (f046b917)
- Add CheckedInt check for GL texture uploads. (227b2360)
- Implement a threadsafe & revised version of http2PushedStream. (17a4b4f6d)
- Convert dom/base/nsImageLoadingContent.cpp to use AsyncOpen2 and followups along with it (1445670 and 1373780 part 2 and 3) (deae241f)
and ported part of tenfourfox changes:
- #559: M1550498 M1548822 M1540759(partial) M1528481(+WeakPtr for Http2Stream) M1555523 M1552541 (46496870)
- #559: M1547266 (97b8db0b)
This commit is contained in:
2019-08-18 15:42:59 +08:00
parent 9fab8d0894
commit 978d4a7dac
41 changed files with 477 additions and 164 deletions
+21
View File
@@ -22,6 +22,7 @@
#include "nsIDOMWindow.h"
#include "nsITabChild.h"
#include "nsIContent.h"
#include "nsIImageLoadingContent.h"
#include "nsILoadContext.h"
#include "nsCOMArray.h"
#include "nsContentUtils.h"
@@ -145,6 +146,16 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
decision);
if (NS_SUCCEEDED(rv) && NS_CP_REJECTED(*decision)) {
// If we are blocking an image, we have to let the
// ImageLoadingContent know that we blocked the load.
if (externalType == nsIContentPolicy::TYPE_IMAGE ||
externalType == nsIContentPolicy::TYPE_IMAGESET) {
nsCOMPtr<nsIImageLoadingContent> img =
do_QueryInterface(requestingContext);
if (img) {
img->SetBlockedRequest(*decision);
}
}
/* policy says no, no point continuing to check */
return NS_OK;
}
@@ -193,6 +204,16 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
decision);
if (NS_SUCCEEDED(rv) && NS_CP_REJECTED(*decision)) {
// If we are blocking an image, we have to let the
// ImageLoadingContent know that we blocked the load.
if (externalType == nsIContentPolicy::TYPE_IMAGE ||
externalType == nsIContentPolicy::TYPE_IMAGESET) {
nsCOMPtr<nsIImageLoadingContent> img =
do_QueryInterface(requestingContext);
if (img) {
img->SetBlockedRequest(*decision);
}
}
/* policy says no, no point continuing to check */
return NS_OK;
}
+3 -6
View File
@@ -8516,12 +8516,9 @@ nsContentUtils::InternalContentPolicyTypeToExternalOrWorker(nsContentPolicyType
bool
nsContentUtils::IsPreloadType(nsContentPolicyType aType)
{
if (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD) {
return true;
}
return false;
return (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD);
}
nsresult
+14 -8
View File
@@ -9363,19 +9363,23 @@ already_AddRefed<nsIURI>
nsDocument::ResolvePreloadImage(nsIURI *aBaseURI,
const nsAString& aSrcAttr,
const nsAString& aSrcsetAttr,
const nsAString& aSizesAttr)
const nsAString& aSizesAttr,
bool *aIsImgSet)
{
nsString sourceURL;
bool isImgSet;
if (mPreloadPictureDepth == 1 && !mPreloadPictureFoundSource.IsVoid()) {
// We're in a <picture> element and found a URI from a source previous to
// this image, use it.
sourceURL = mPreloadPictureFoundSource;
isImgSet = true;
} else {
// Otherwise try to use this <img> as a source
HTMLImageElement::SelectSourceForTagWithAttrs(this, false, aSrcAttr,
aSrcsetAttr, aSizesAttr,
NullString(), NullString(),
sourceURL);
isImgSet = !aSrcsetAttr.IsEmpty();
}
// Empty sources are not loaded by <img> (i.e. not resolved to the baseURI)
@@ -9393,6 +9397,8 @@ nsDocument::ResolvePreloadImage(nsIURI *aBaseURI,
return nullptr;
}
*aIsImgSet = isImgSet;
// We don't clear mPreloadPictureFoundSource because subsequent <img> tags in
// this this <picture> share the same <sources> (though this is not valid per
// spec)
@@ -9401,16 +9407,12 @@ nsDocument::ResolvePreloadImage(nsIURI *aBaseURI,
void
nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
ReferrerPolicy aReferrerPolicy)
ReferrerPolicy aReferrerPolicy, bool aIsImgSet)
{
// Early exit if the img is already present in the img-cache
// which indicates that the "real" load has already started and
// that we shouldn't preload it.
int16_t blockingStatus;
if (nsContentUtils::IsImageInCache(uri, static_cast<nsIDocument *>(this)) ||
!nsContentUtils::CanLoadImage(uri, static_cast<nsIDocument *>(this),
this, NodePrincipal(), &blockingStatus,
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD)) {
if (nsContentUtils::IsImageInCache(uri, static_cast<nsIDocument *>(this))) {
return;
}
@@ -9429,6 +9431,10 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
MOZ_CRASH("Unknown CORS mode!");
}
nsContentPolicyType policyType =
aIsImgSet ? nsIContentPolicy::TYPE_IMAGESET :
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD;
// Image not in cache - trigger preload
RefPtr<imgRequestProxy> request;
nsresult rv =
@@ -9442,7 +9448,7 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
loadFlags,
NS_LITERAL_STRING("img"),
getter_AddRefs(request),
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD);
policyType);
// Pin image-reference to avoid evicting it from the img-cache before
// the "real" load occurs. Unpinned in DispatchContentLoadedEvents and
+4 -2
View File
@@ -963,11 +963,13 @@ public:
ResolvePreloadImage(nsIURI *aBaseURI,
const nsAString& aSrcAttr,
const nsAString& aSrcsetAttr,
const nsAString& aSizesAttr) override;
const nsAString& aSizesAttr,
bool *aIsImgSet) override;
virtual void MaybePreLoadImage(nsIURI* uri,
const nsAString &aCrossOriginAttr,
ReferrerPolicy aReferrerPolicy) override;
ReferrerPolicy aReferrerPolicy,
bool aIsImgSet) override;
virtual void ForgetImagePreload(nsIURI* aURI) override;
virtual void MaybePreconnect(nsIURI* uri,
+6 -4
View File
@@ -2407,11 +2407,13 @@ nsGlobalWindow::WouldReuseInnerWindow(nsIDocument* aNewDocument)
}
bool equal;
if (NS_SUCCEEDED(mDoc->NodePrincipal()->Equals(aNewDocument->NodePrincipal(),
&equal)) &&
equal) {
if (NS_SUCCEEDED(
BasePrincipal::Cast(mDoc->NodePrincipal())->
EqualsConsideringDomain(aNewDocument->NodePrincipal(),
&equal))) {
// Return the result. If true (bug 1552541):
// The origin is the same.
return true;
return equal;
}
return false;
+8 -2
View File
@@ -2309,21 +2309,27 @@ public:
* nesting and possible sources, which are used to inform URL selection
* responsive <picture> or <img srcset> images. Unset attributes are expected
* to be marked void.
* If this image is for <picture> or <img srcset>, aIsImgSet will be set to
* true, false otherwise.
*/
virtual already_AddRefed<nsIURI>
ResolvePreloadImage(nsIURI *aBaseURI,
const nsAString& aSrcAttr,
const nsAString& aSrcsetAttr,
const nsAString& aSizesAttr) = 0;
const nsAString& aSizesAttr,
bool *aIsImgSet) = 0;
/**
* Called by nsParser to preload images. Can be removed and code moved
* to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
* parser-module is linked with gklayout-module. aCrossOriginAttr should
* be a void string if the attr is not present.
* aIsImgSet is the value got from calling ResolvePreloadImage, it is true
* when this image is for loading <picture> or <img srcset> images.
*/
virtual void MaybePreLoadImage(nsIURI* uri,
const nsAString& aCrossOriginAttr,
ReferrerPolicyEnum aReferrerPolicy) = 0;
ReferrerPolicyEnum aReferrerPolicy,
bool aIsImgSet) = 0;
/**
* Called by images to forget an image preload when they start doing
+9
View File
@@ -103,6 +103,15 @@ interface nsIImageLoadingContent : imgINotificationObserver
*/
imgIRequest getRequest(in long aRequestType);
/**
* Call this function when the request was blocked by any of the
* security policies enforced.
*
* @param aContentDecision the decision returned from nsIContentPolicy
* (any of the types REJECT_*)
*/
void setBlockedRequest(in int16_t aContentDecision);
/**
* @return true if the current request's size is available.
*/
+50 -49
View File
@@ -44,6 +44,7 @@
#include "mozAutoDocUpdate.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/EventStates.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ImageTracker.h"
@@ -95,6 +96,7 @@ nsImageLoadingContent::nsImageLoadingContent()
mStateChangerDepth(0),
mCurrentRequestRegistered(false),
mPendingRequestRegistered(false),
mIsStartingImageLoad(false),
mFrameCreateCalled(false)
{
if (!nsContentUtils::GetImgLoaderForChannel(nullptr, nullptr)) {
@@ -790,6 +792,11 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
nsIDocument* aDocument,
nsLoadFlags aLoadFlags)
{
MOZ_ASSERT(!mIsStartingImageLoad, "some evil code is reentering LoadImage.");
if (mIsStartingImageLoad) {
return NS_OK;
}
// Pending load/error events need to be canceled in some situations. This
// is not documented in the spec, but can cause site compat problems if not
// done. See bug 1309461 and https://github.com/whatwg/html/issues/1872.
@@ -819,6 +826,21 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
}
}
AutoRestore<bool> guard(mIsStartingImageLoad);
mIsStartingImageLoad = true;
// Data documents, or documents from DOMParser shouldn't perform image loading.
if (aDocument->IsLoadedAsData()) {
// This is the only codepath on which we can reach SetBlockedRequest while
// our pending request exists. Just clear it out here if we do have one.
ClearPendingRequest(NS_BINDING_ABORTED,
Some(OnNonvisible::DISCARD_IMAGES));
SetBlockedRequest(nsIContentPolicy::REJECT_REQUEST);
FireEvent(NS_LITERAL_STRING("error"));
FireEvent(NS_LITERAL_STRING("loadend"));
return NS_OK;
}
// URI equality check.
//
// We skip the equality check if our current image was blocked, since in that
@@ -849,23 +871,8 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
"Principal mismatch?");
#endif
// Are we blocked?
int16_t cpDecision = nsIContentPolicy::REJECT_REQUEST;
nsContentPolicyType policyType = PolicyTypeForLoad(aImageLoadType);
nsContentUtils::CanLoadImage(aNewURI,
static_cast<nsIImageLoadingContent*>(this),
aDocument,
aDocument->NodePrincipal(),
&cpDecision,
policyType);
if (!NS_CP_ACCEPTED(cpDecision)) {
FireEvent(NS_LITERAL_STRING("error"));
FireEvent(NS_LITERAL_STRING("loadend"));
SetBlockedRequest(aNewURI, cpDecision);
return NS_OK;
}
nsLoadFlags loadFlags = aLoadFlags;
int32_t corsmode = GetCORSMode();
if (corsmode == CORS_ANONYMOUS) {
@@ -883,7 +890,6 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
referrerPolicy = imgReferrerPolicy;
}
// Not blocked. Do the load.
RefPtr<imgRequestProxy>& req = PrepareNextRequest(aImageLoadType);
nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
@@ -937,7 +943,6 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
FireEvent(NS_LITERAL_STRING("error"));
FireEvent(NS_LITERAL_STRING("loadend"));
return NS_OK;
}
return NS_OK;
@@ -1217,46 +1222,42 @@ nsImageLoadingContent::PrepareNextRequest(ImageLoadType aImageLoadType)
mMostRecentRequestChange = now;
}
// If we don't have a usable current request, get rid of any half-baked
// request that might be sitting there and make this one current.
if (!HaveSize(mCurrentRequest))
return PrepareCurrentRequest(aImageLoadType);
// Otherwise, make it pending.
return PreparePendingRequest(aImageLoadType);
// We only want to cancel the existing current request if size is not
// available. bz says the web depends on this behavior.
// Otherwise, we get rid of any half-baked request that might be sitting there
// and make this one current.
// TODO: Bug 583491
// Investigate/Cleanup NS_ERROR_IMAGE_SRC_CHANGED use in nsImageFrame.cpp
return HaveSize(mCurrentRequest) ?
PreparePendingRequest(aImageLoadType) :
PrepareCurrentRequest(aImageLoadType);
}
void
nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, int16_t aContentDecision)
nsresult
nsImageLoadingContent::SetBlockedRequest(int16_t aContentDecision)
{
// If this is not calling from LoadImage, for example, from ServiceWorker,
// bail out.
if (!mIsStartingImageLoad) {
return NS_OK;
}
// Sanity
MOZ_ASSERT(!NS_CP_ACCEPTED(aContentDecision), "Blocked but not?");
// We do some slightly illogical stuff here to maintain consistency with
// old behavior that people probably depend on. Even in the case where the
// new image is blocked, the old one should really be canceled with the
// reason "image source changed". However, apparently there's some abuse
// over in nsImageFrame where the displaying of the "broken" icon for the
// next image depends on the cancel reason of the previous image. ugh.
// XXX(seth): So shouldn't we fix nsImageFrame?!
ClearPendingRequest(NS_ERROR_IMAGE_BLOCKED,
Some(OnNonvisible::DISCARD_IMAGES));
// For the blocked case, we only want to cancel the existing current request
// if size is not available. bz says the web depends on this behavior.
if (!HaveSize(mCurrentRequest)) {
// We should never have a pending request after we got blocked.
MOZ_ASSERT(!mPendingRequest, "mPendingRequest should be null.");
if (HaveSize(mCurrentRequest)) {
// PreparePendingRequest set mPendingRequestFlags, now since we've decided
// to block it, we reset it back to 0.
mPendingRequestFlags = 0;
} else {
mImageBlockingStatus = aContentDecision;
uint32_t keepFlags = mCurrentRequestFlags & REQUEST_IS_IMAGESET;
ClearCurrentRequest(NS_ERROR_IMAGE_BLOCKED,
Some(OnNonvisible::DISCARD_IMAGES));
// We still want to remember what URI we were and if it was an imageset,
// despite not having an actual request. These are both cleared as part of
// ClearCurrentRequest() before a new request is started.
mCurrentURI = aURI;
mCurrentRequestFlags = keepFlags;
}
return NS_OK;
}
RefPtr<imgRequestProxy>&
@@ -1267,7 +1268,7 @@ nsImageLoadingContent::PrepareCurrentRequest(ImageLoadType aImageLoadType)
mImageBlockingStatus = nsIContentPolicy::ACCEPT;
// Get rid of anything that was there previously.
ClearCurrentRequest(NS_ERROR_IMAGE_SRC_CHANGED,
ClearCurrentRequest(NS_BINDING_ABORTED,
Some(OnNonvisible::DISCARD_IMAGES));
if (mNewRequestsWillNeedAnimationReset) {
@@ -1286,7 +1287,7 @@ RefPtr<imgRequestProxy>&
nsImageLoadingContent::PreparePendingRequest(ImageLoadType aImageLoadType)
{
// Get rid of anything that was there previously.
ClearPendingRequest(NS_ERROR_IMAGE_SRC_CHANGED,
ClearPendingRequest(NS_BINDING_ABORTED,
Some(OnNonvisible::DISCARD_IMAGES));
if (mNewRequestsWillNeedAnimationReset) {
+9 -8
View File
@@ -302,18 +302,11 @@ protected:
*/
RefPtr<imgRequestProxy>& PrepareNextRequest(ImageLoadType aImageLoadType);
/**
* Called when we would normally call PrepareNextRequest(), but the request was
* blocked.
*/
void SetBlockedRequest(nsIURI* aURI, int16_t aContentDecision);
/**
* Returns a COMPtr reference to the current/pending image requests, cleaning
* up and canceling anything that was there before. Note that if you just want
* to get rid of one of the requests, you should call
* Clear*Request(NS_BINDING_ABORTED) instead, since it passes a more appropriate
* aReason than Prepare*Request() does (NS_ERROR_IMAGE_SRC_CHANGED).
* Clear*Request(NS_BINDING_ABORTED) instead.
*
* @param aImageLoadType The ImageLoadType for this request
*/
@@ -455,6 +448,14 @@ private:
bool mCurrentRequestRegistered;
bool mPendingRequestRegistered;
// This member is used in SetBlockedRequest, if it's true, then this call is
// triggered from LoadImage.
// If this is false, it means this call is from other places like
// ServiceWorker, then we will ignore call to SetBlockedRequest for now.
//
// Also we use this variable to check if some evil code is reentering LoadImage.
bool mIsStartingImageLoad;
// True when FrameCreate has been called but FrameDestroy has not.
bool mFrameCreateCalled;
};
+1
View File
@@ -134,6 +134,7 @@ WebGLBuffer::BufferData(GLenum target, size_t size, const void* data, GLenum usa
if (error) {
MOZ_ASSERT(error == LOCAL_GL_OUT_OF_MEMORY);
mContext->ErrorOutOfMemory("%s: Error from driver: 0x%04x", funcName, error);
mByteLength = 0;
return;
}
} else {
+10
View File
@@ -215,6 +215,16 @@ WebGLRenderbuffer::RenderbufferStorage(const char* funcName, uint32_t samples,
if (error) {
const char* errorName = mContext->ErrorName(error);
mContext->GenerateWarning("%s generated error %s", funcName, errorName);
if (error == LOCAL_GL_OUT_OF_MEMORY) {
// Truncate.
mSamples = 0;
mFormat = nullptr;
mWidth = 0;
mHeight = 0;
mImageDataStatus = WebGLImageDataStatus::NoImageData;
InvalidateStatusOfAttachedFBs(funcName);
}
return;
}
+6
View File
@@ -1222,6 +1222,12 @@ WebGLTexture::TexParameter(TexTarget texTarget, GLenum pname, const FloatOrInt&
mContext->gl->fTexParameterf(texTarget.get(), pname, clamped.f);
}
void WebGLTexture::Truncate(const char* funcName) {
for (auto& cur : mImageInfoArr) {
SetImageInfo(funcName, &cur, ImageInfo());
}
}
////////////////////////////////////////////////////////////////////////////////
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTexture)
+1
View File
@@ -387,6 +387,7 @@ public:
bool* const out_initFailed);
bool IsMipmapCubeComplete() const;
void Truncate(const char* funcName);
bool IsCubeMap() const { return (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP); }
+7 -1
View File
@@ -1170,6 +1170,7 @@ WebGLTexture::TexStorage(const char* funcName, TexTarget target, GLsizei levels,
if (error == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Ran out of memory during texture allocation.",
funcName);
Truncate(funcName);
return;
}
if (error) {
@@ -1302,6 +1303,7 @@ WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level,
if (glError == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Driver ran out of memory during upload.",
funcName);
Truncate(funcName);
return;
}
@@ -1390,6 +1392,7 @@ WebGLTexture::TexSubImage(const char* funcName, TexImageTarget target, GLint lev
if (glError == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Driver ran out of memory during upload.",
funcName);
Truncate(funcName);
return;
}
@@ -1506,6 +1509,7 @@ WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GL
blob->mAvailBytes, blob->mPtr);
if (error == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Ran out of memory during upload.", funcName);
Truncate(funcName);
return;
}
if (error) {
@@ -1656,6 +1660,7 @@ WebGLTexture::CompressedTexSubImage(const char* funcName, TexImageTarget target,
blob->mAvailBytes, blob->mPtr);
if (error == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Ran out of memory during upload.", funcName);
Truncate(funcName);
return;
}
if (error) {
@@ -1998,7 +2003,7 @@ WebGLTexture::ValidateCopyTexImageForFeedback(const char* funcName, uint32_t lev
static bool
DoCopyTexOrSubImage(WebGLContext* webgl, const char* funcName, bool isSubImage,
const WebGLTexture* tex, TexImageTarget target, GLint level,
WebGLTexture* tex, TexImageTarget target, GLint level,
GLint xWithinSrc, GLint yWithinSrc,
uint32_t srcTotalWidth, uint32_t srcTotalHeight,
const webgl::FormatUsageInfo* srcUsage,
@@ -2075,6 +2080,7 @@ DoCopyTexOrSubImage(WebGLContext* webgl, const char* funcName, bool isSubImage,
if (error == LOCAL_GL_OUT_OF_MEMORY) {
webgl->ErrorOutOfMemory("%s: Ran out of memory during texture copy.", funcName);
tex->Truncate(funcName);
return false;
}
+2 -1
View File
@@ -186,7 +186,8 @@ bool
MP4Decoder::IsH264(const nsACString& aMimeType)
{
return aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc");
aMimeType.EqualsLiteral("video/avc") ||
aMimeType.EqualsLiteral("video/webm; codecs=avc1");
}
/* static */
@@ -701,6 +701,10 @@ ContainerParser::CreateForMIMEType(const MediaContainerType& aType)
return new WebMContainerParser(aType);
}
if (aType.Type() == MEDIAMIMETYPE("video/x-matroska")) {
return new WebMContainerParser(aType);
}
#ifdef MOZ_FMP4
if (aType.Type() == MEDIAMIMETYPE("video/mp4")
|| aType.Type() == MEDIAMIMETYPE("audio/mp4")) {
+2 -1
View File
@@ -113,7 +113,8 @@ MediaSource::IsTypeSupported(const nsAString& aType, DecoderDoctorDiagnostics* a
}
return NS_OK;
}
if (mimeType == MEDIAMIMETYPE("video/webm")) {
if (mimeType == MEDIAMIMETYPE("video/webm") ||
mimeType == MEDIAMIMETYPE("video/x-matroska")) {
if (!(Preferences::GetBool("media.mediasource.webm.enabled", false) ||
IsWebMForced(aDiagnostics))) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
@@ -814,6 +814,7 @@ TrackBuffersManager::CreateDemuxerforMIMEType()
ShutdownDemuxers();
if (mType.Type() == MEDIAMIMETYPE("video/webm") ||
mType.Type() == MEDIAMIMETYPE("video/x-matroska") ||
mType.Type() == MEDIAMIMETYPE("audio/webm")) {
mInputDemuxer = new WebMDemuxer(mCurrentInputBuffer, true /* IsMediaSource*/ );
return;
+9
View File
@@ -60,6 +60,15 @@ WebMDecoder::IsSupportedType(const MediaContainerType& aContainerType)
continue;
}
#endif
if (IsH264CodecString(codec)) {
continue;
}
if (IsAACCodecString(codec)) {
continue;
}
// Some unsupported codec.
return false;
}
+25 -1
View File
@@ -326,6 +326,20 @@ WebMDemuxer::ReadMetadata()
case NESTEGG_CODEC_AV1:
mInfo.mVideo.mMimeType = "video/webm; codecs=av1";
break;
case NESTEGG_CODEC_AVC1: {
mInfo.mVideo.mMimeType = "video/webm; codecs=avc1";
unsigned char* data = 0;
size_t length = 0;
r = nestegg_track_codec_data(context, track, 0, &data, &length);
if (r == -1) {
return NS_ERROR_FAILURE;
}
mInfo.mVideo.mExtraData = new MediaByteBuffer(length);
mInfo.mVideo.mExtraData->AppendElements(data, length);
break;
}
default:
NS_WARNING("Unknown WebM video codec");
return NS_ERROR_FAILURE;
@@ -409,6 +423,8 @@ WebMDemuxer::ReadMetadata()
mInfo.mAudio.mMimeType = "audio/opus";
OpusDataDecoder::AppendCodecDelay(mInfo.mAudio.mCodecSpecificConfig,
media::TimeUnit::FromNanoseconds(params.codec_delay).ToMicroseconds());
} else if (mAudioCodec == NESTEGG_CODEC_AAC) {
mInfo.mAudio.mMimeType = "audio/mp4a-latm";
}
mSeekPreroll = params.seek_preroll;
mInfo.mAudio.mRate = params.rate;
@@ -678,6 +694,9 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
isKeyframe = AOMDecoder::IsKeyframe(sample);
break;
#endif
case NESTEGG_CODEC_AVC1:
isKeyframe = nestegg_packet_has_keyframe(holder->Packet());
break;
default:
NS_WARNING("Cannot detect keyframes in unknown WebM video codec");
return NS_ERROR_FAILURE;
@@ -698,7 +717,7 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
dimensions = AOMDecoder::GetFrameSize(sample);
break;
#endif
}
}
if (mLastSeenFrameSize.isSome()
&& (dimensions != mLastSeenFrameSize.value())) {
mInfo.mVideo.mDisplay = dimensions;
@@ -774,6 +793,11 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
if (aType == TrackInfo::kVideoTrack) {
sample->mTrackInfo = mSharedVideoTrackInfo;
}
if (mVideoCodec == NESTEGG_CODEC_AVC1) {
sample->mExtraData = mInfo.mVideo.mExtraData;
}
aSamples->Push(sample);
}
return NS_OK;
@@ -1381,7 +1381,7 @@ nsPluginStreamListenerPeer::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsICh
return NS_ERROR_FAILURE;
}
// Don't allow cross-origin 307 POST redirects.
// Don't allow cross-origin 307/308 POST redirects.
nsCOMPtr<nsIHttpChannel> oldHttpChannel(do_QueryInterface(oldChannel));
if (oldHttpChannel) {
uint32_t responseStatus;
@@ -1389,7 +1389,7 @@ nsPluginStreamListenerPeer::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsICh
if (NS_FAILED(rv)) {
return rv;
}
if (responseStatus == 307) {
if (responseStatus == 307 || responseStatus == 308) {
nsAutoCString method;
rv = oldHttpChannel->GetRequestMethod(method);
if (NS_FAILED(rv)) {
@@ -12,6 +12,7 @@
#include "nsMixedContentBlocker.h"
#include "nsCDefaultURIFixup.h"
#include "nsIURIFixup.h"
#include "nsIImageLoadingContent.h"
#include "nsINestedURI.h"
#include "mozilla/dom/Element.h"
@@ -732,6 +733,8 @@ nsContentSecurityManager::CheckChannel(nsIChannel* aChannel)
// within nsCorsListenerProxy
rv = DoCheckLoadURIChecks(uri, loadInfo);
NS_ENSURE_SUCCESS(rv, rv);
// TODO: Bug 1371237
// consider calling SetBlockedRequest in nsContentSecurityManager::CheckChannel
}
return NS_OK;
+37 -3
View File
@@ -178,7 +178,22 @@ TexSubImage2DWithoutUnpackSubimage(GLContext* gl,
// isn't supported. We make a copy of the texture data we're using,
// such that we're using the whole row of data in the copy. This turns
// out to be more efficient than uploading row-by-row; see bug 698197.
unsigned char* newPixels = new (fallible) unsigned char[width*height*pixelsize];
// Width and height are never more than 16384. At 16Ki*16Ki, 4Bpp is 1GiB, but
// if we allow 8Bpp (16-bit channels, or higher) here, that's 2GiB+, which would
// overflow on 32-bit.
MOZ_ASSERT(width <= 16384);
MOZ_ASSERT(height <= 16384);
MOZ_ASSERT(pixelsize < 8);
const auto size = CheckedInt<size_t>(width) * height * pixelsize;
if (!size.isValid()) {
// This should never happen, but we use a defensive check.
MOZ_ASSERT_UNREACHABLE("Unacceptable size calculated.!");
return;
}
unsigned char* newPixels = new (fallible) unsigned char[size.value()];
if (newPixels) {
unsigned char* rowDest = newPixels;
@@ -303,7 +318,22 @@ TexImage2DHelper(GLContext* gl,
GLsizei paddedWidth = RoundUpPow2((uint32_t)width);
GLsizei paddedHeight = RoundUpPow2((uint32_t)height);
GLvoid* paddedPixels = new unsigned char[paddedWidth * paddedHeight * pixelsize];
// Width and height are never more than 16384. At 16Ki*16Ki, 4Bpp
// is 1GiB, but if we allow 8Bpp (or higher) here, that's 2GiB,
// which would overflow on 32-bit.
MOZ_ASSERT(width <= 16384);
MOZ_ASSERT(height <= 16384);
MOZ_ASSERT(pixelsize < 8);
const auto size =
CheckedInt<size_t>(paddedWidth) * paddedHeight * pixelsize;
if (!size.isValid()) {
// This should never happen, but we use a defensive check.
MOZ_ASSERT_UNREACHABLE("Unacceptable size calculated.!");
return;
}
GLvoid* paddedPixels = new unsigned char[size.value()];
// Pad out texture data to be in a POT sized buffer for uploading to
// a POT sized texture
@@ -483,13 +513,17 @@ UploadImageDataToTexture(GLContext* gl,
surfaceFormat = SurfaceFormat::A8;
break;
default:
NS_ASSERTION(false, "Unhandled image surface format!");
MOZ_ASSERT_UNREACHABLE(false, "Unhandled image surface format!");
}
if (aOutUploadSize) {
*aOutUploadSize = 0;
}
if (surfaceFormat == gfx::SurfaceFormat::UNKNOWN) {
return gfx::SurfaceFormat::UNKNOWN;
}
if (aNeedInit || !CanUploadSubTextures(gl)) {
// If the texture needs initialized, or we are unable to
// upload sub textures, then initialize and upload the entire
+1
View File
@@ -1697,6 +1697,7 @@ imgLoader::ValidateRequestWithNewChannel(imgRequest* request,
rv = newChannel->AsyncOpen2(listener);
if (NS_WARN_IF(NS_FAILED(rv))) {
req->CancelAndForgetObserver(rv);
return false;
}
+2
View File
@@ -72,6 +72,8 @@ extern "C" {
#define NESTEGG_CODEC_VP9 2 /**< Track uses Google On2 VP9 codec. */
#define NESTEGG_CODEC_OPUS 3 /**< Track uses Xiph Opus codec. */
#define NESTEGG_CODEC_AV1 4 /**< Track uses AOMedia AV1 codec. */
#define NESTEGG_CODEC_AVC1 5 /**< Track uses AVC1 'h264' */
#define NESTEGG_CODEC_AAC 6 /**< Track uses AAC 'mp4a' */
#define NESTEGG_CODEC_UNKNOWN INT_MAX /**< Track uses unknown codec. */
#define NESTEGG_VIDEO_MONO 0 /**< Track is mono video. */
+26 -2
View File
@@ -157,6 +157,8 @@ enum ebml_type_enum {
#define TRACK_ID_AV1 "V_AV1"
#define TRACK_ID_VORBIS "A_VORBIS"
#define TRACK_ID_OPUS "A_OPUS"
#define TRACK_ID_AVC1 "V_MPEG4/ISO/AVC"
#define TRACK_ID_AAC "A_AAC"
/* Track Encryption */
#define CONTENT_ENC_ALGO_AES 5
@@ -2401,6 +2403,12 @@ nestegg_track_codec_id(nestegg * ctx, unsigned int track)
if (strcmp(codec_id, TRACK_ID_OPUS) == 0)
return NESTEGG_CODEC_OPUS;
if (strcmp(codec_id, TRACK_ID_AVC1) == 0)
return NESTEGG_CODEC_AVC1;
if (strcmp(codec_id, TRACK_ID_AAC) == 0)
return NESTEGG_CODEC_AAC;
return NESTEGG_CODEC_UNKNOWN;
}
@@ -2421,7 +2429,8 @@ nestegg_track_codec_data_count(nestegg * ctx, unsigned int track,
codec_id = nestegg_track_codec_id(ctx, track);
if (codec_id == NESTEGG_CODEC_OPUS) {
if (codec_id == NESTEGG_CODEC_OPUS ||
codec_id == NESTEGG_CODEC_AAC) {
*count = 1;
return 0;
}
@@ -2459,7 +2468,9 @@ nestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
return -1;
if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS &&
nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS)
nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS &&
nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_AVC1 &&
nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_AAC)
return -1;
if (ne_get_binary(entry->codec_private, &codec_private) != 0)
@@ -2772,6 +2783,19 @@ nestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt)
if (r != 1)
return r;
/* Some files have a crc32 element, since it also has to be first it
conflicts with the timecode spec. Just ignore it */
if (id == ID_CRC32) {
ctx->log(ctx, NESTEGG_LOG_DEBUG,
"read_packet: skipping crc element in a cluster");
r = ne_io_read_skip(ctx->io, size);
if (r != 1)
return r;
r = ne_read_element(ctx, &id, &size);
if (r != 1)
return r;
}
/* Timecode must be the first element in a Cluster, per spec. */
if (id != ID_TIMECODE)
return -1;
+1 -1
View File
@@ -521,7 +521,7 @@ nsStandardURL::ValidIPv6orHostname(const char *host, uint32_t length)
}
const char *end = host + length;
if (end != net_FindCharInSet(host, end, CONTROL_CHARACTERS " #/:?@[\\]*<>|\"")) {
if (end != net_FindCharInSet(host, end, CONTROL_CHARACTERS " #/:?@[\\]*<>|\"^")) {
// We still allow % because it is in the ID of addons.
// Any percent encoded ASCII characters that are not allowed in the
// hostname are not percent decoded, and will be parsed just fine.
+78 -4
View File
@@ -30,8 +30,8 @@ class CallChannelOnPush final : public Runnable {
Http2PushedStream *pushStream)
: mAssociatedChannel(associatedChannel)
, mPushedURI(pushedURI)
, mPushedStream(pushStream)
{
mPushedStreamWrapper = new Http2PushedStreamWrapper(pushStream);
}
NS_IMETHOD Run() override
@@ -40,21 +40,95 @@ class CallChannelOnPush final : public Runnable {
RefPtr<nsHttpChannel> channel;
CallQueryInterface(mAssociatedChannel, channel.StartAssignment());
MOZ_ASSERT(channel);
if (channel && NS_SUCCEEDED(channel->OnPush(mPushedURI, mPushedStream))) {
if (channel &&
NS_SUCCEEDED(channel->OnPush(mPushedURI, mPushedStreamWrapper))) {
return NS_OK;
}
LOG3(("Http2PushedStream Orphan %p failed OnPush\n", this));
mPushedStream->OnPushFailed();
mPushedStreamWrapper->OnPushFailed();
return NS_OK;
}
private:
nsCOMPtr<nsIHttpChannelInternal> mAssociatedChannel;
const nsCString mPushedURI;
Http2PushedStream *mPushedStream;
RefPtr<Http2PushedStreamWrapper> mPushedStreamWrapper;
};
// Because WeakPtr isn't thread-safe we must ensure that the object is destroyed
// on the socket thread, so any Release() called on a different thread is
// dispatched to the socket thread.
bool Http2PushedStreamWrapper::DispatchRelease() {
if (PR_GetCurrentThread() == gSocketThread) {
return false;
}
gSocketTransportService->Dispatch(
NewNonOwningRunnableMethod(this, &Http2PushedStreamWrapper::Release),
NS_DISPATCH_NORMAL);
return true;
}
NS_IMPL_ADDREF(Http2PushedStreamWrapper)
NS_IMETHODIMP_(MozExternalRefCountType)
Http2PushedStreamWrapper::Release() {
nsrefcnt count = mRefCnt - 1;
if (DispatchRelease()) {
// Redispatched to the socket thread.
return count;
}
MOZ_ASSERT(0 != mRefCnt, "dup release");
count = --mRefCnt;
NS_LOG_RELEASE(this, count, "Http2PushedStreamWrapper");
if (0 == count) {
mRefCnt = 1;
delete (this);
return 0;
}
return count;
}
NS_INTERFACE_MAP_BEGIN(Http2PushedStreamWrapper)
NS_INTERFACE_MAP_END
Http2PushedStreamWrapper::Http2PushedStreamWrapper(
Http2PushedStream* aPushStream) {
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "not on socket thread");
mStream = aPushStream;
mRequestString = aPushStream->GetRequestString();
}
Http2PushedStreamWrapper::~Http2PushedStreamWrapper() {
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "not on socket thread");
}
Http2PushedStream* Http2PushedStreamWrapper::GetStream() {
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "not on socket thread");
if (mStream) {
Http2Stream* stream = mStream;
return static_cast<Http2PushedStream*>(stream);
}
return nullptr;
}
void Http2PushedStreamWrapper::OnPushFailed() {
if (PR_GetCurrentThread() == gSocketThread) {
if (mStream) {
Http2Stream* stream = mStream;
static_cast<Http2PushedStream*>(stream)->OnPushFailed();
}
} else {
gSocketTransportService->Dispatch(
NewRunnableMethod(this, &Http2PushedStreamWrapper::OnPushFailed),
NS_DISPATCH_NORMAL);
}
}
//////////////////////////////////////////
// Http2PushedStream
//////////////////////////////////////////
+18
View File
@@ -123,6 +123,24 @@ private:
uint32_t mBufferedHTTP1Consumed;
};
class Http2PushedStreamWrapper : public nsISupports {
public:
NS_DECL_THREADSAFE_ISUPPORTS
bool DispatchRelease();
explicit Http2PushedStreamWrapper(Http2PushedStream* aPushStream);
nsCString& GetRequestString() { return mRequestString; }
Http2PushedStream* GetStream();
void OnPushFailed();
private:
virtual ~Http2PushedStreamWrapper();
nsCString mRequestString;
WeakPtr<Http2Stream> mStream;
};
} // namespace net
} // namespace mozilla
+44 -27
View File
@@ -387,12 +387,24 @@ Http2Session::AddStream(nsAHttpTransaction *aHttpTransaction,
if (mClosed || mShouldGoAway) {
nsHttpTransaction *trans = aHttpTransaction->QueryHttpTransaction();
if (trans && !trans->GetPushedStream()) {
LOG3(("Http2Session::AddStream %p atrans=%p trans=%p session unusable - resched.\n",
this, aHttpTransaction, trans));
aHttpTransaction->SetConnection(nullptr);
gHttpHandler->InitiateTransaction(trans, trans->Priority());
return true;
if (trans) {
RefPtr<Http2PushedStreamWrapper> pushedStreamWrapper;
pushedStreamWrapper = trans->GetPushedStream();
if (!pushedStreamWrapper || !pushedStreamWrapper->GetStream()) {
LOG3(
("Http2Session::AddStream %p atrans=%p trans=%p session unusable - "
"resched.\n", this, aHttpTransaction, trans));
aHttpTransaction->SetConnection(nullptr);
nsresult rv =
gHttpHandler->InitiateTransaction(trans, trans->Priority());
if (NS_FAILED(rv)) {
LOG3(
("Http2Session::AddStream %p atrans=%p trans=%p failed to "
"initiate transaction (%08x).\n",
this, aHttpTransaction, trans, static_cast<uint32_t>(rv)));
}
return true;
}
}
}
@@ -1726,8 +1738,9 @@ Http2Session::RecvPushPromise(Http2Session *self)
RefPtr<Http2PushTransactionBuffer> transactionBuffer =
new Http2PushTransactionBuffer();
transactionBuffer->SetConnection(self);
Http2PushedStream *pushedStream =
new Http2PushedStream(transactionBuffer, self, associatedStream, promisedID);
nsAutoPtr<Http2PushedStream> pushedStream(
new Http2PushedStream(transactionBuffer, self, associatedStream, promisedID)
);
rv = pushedStream->ConvertPushHeaders(&self->mDecompressor,
self->mDecompressBuffer,
@@ -1736,7 +1749,6 @@ Http2Session::RecvPushPromise(Http2Session *self)
if (rv == NS_ERROR_NOT_IMPLEMENTED) {
LOG3(("Http2Session::PushPromise Semantics not Implemented\n"));
self->GenerateRstStream(REFUSED_STREAM_ERROR, promisedID);
delete pushedStream;
self->ResetDownstreamState();
return NS_OK;
}
@@ -1745,7 +1757,6 @@ Http2Session::RecvPushPromise(Http2Session *self)
// This means the decompression completed ok, but there was a problem with
// the decoded headers. Reset the stream and go away.
self->GenerateRstStream(PROTOCOL_ERROR, promisedID);
delete pushedStream;
self->ResetDownstreamState();
return NS_OK;
} else if (NS_FAILED(rv)) {
@@ -1754,14 +1765,17 @@ Http2Session::RecvPushPromise(Http2Session *self)
return rv;
}
WeakPtr<Http2Stream> pushedWeak = pushedStream.forget();
// Ownership of the pushed stream is by the transaction hash, just as it
// is for a client initiated stream. Errors that aren't fatal to the
// whole session must call cleanupStream() after this point in order
// to remove the stream from that hash.
self->mStreamTransactionHash.Put(transactionBuffer, pushedStream);
self->mPushedStreams.AppendElement(pushedStream);
self->mStreamTransactionHash.Put(transactionBuffer, pushedWeak);
self->mPushedStreams.AppendElement(
static_cast<Http2PushedStream*>(pushedWeak.get()));
if (self->RegisterStreamID(pushedStream, promisedID) == kDeadStreamID) {
if (self->RegisterStreamID(pushedWeak, promisedID) == kDeadStreamID) {
LOG3(("Http2Session::RecvPushPromise registerstreamid failed\n"));
self->mGoAwayReason = INTERNAL_ERROR;
return NS_ERROR_FAILURE;
@@ -1773,23 +1787,24 @@ Http2Session::RecvPushPromise(Http2Session *self)
// Fake the request side of the pushed HTTP transaction. Sets up hash
// key and origin
uint32_t notUsed;
pushedStream->ReadSegments(nullptr, 1, &notUsed);
pushedWeak->ReadSegments(nullptr, 1, &notUsed);
nsAutoCString key;
if (!pushedStream->GetHashKey(key)) {
if (!static_cast<Http2PushedStream*>(pushedWeak.get())->GetHashKey(key)) {
LOG3(("Http2Session::RecvPushPromise one of :authority :scheme :path missing from push\n"));
self->CleanupStream(pushedStream, NS_ERROR_FAILURE, PROTOCOL_ERROR);
self->CleanupStream(pushedWeak, NS_ERROR_FAILURE, PROTOCOL_ERROR);
self->ResetDownstreamState();
return NS_OK;
}
// does the pushed origin belong on this connection?
RefPtr<nsStandardURL> associatedURL, pushedURL;
rv = Http2Stream::MakeOriginURL(associatedStream->Origin(), associatedURL);
if (NS_SUCCEEDED(rv)) {
rv = Http2Stream::MakeOriginURL(pushedStream->Origin(), pushedURL);
rv = Http2Stream::MakeOriginURL(pushedWeak->Origin(), pushedURL);
}
LOG3(("Http2Session::RecvPushPromise %p checking %s == %s", self,
associatedStream->Origin().get(), pushedStream->Origin().get()));
associatedStream->Origin().get(), pushedWeak->Origin().get()));
bool match = false;
if (NS_SUCCEEDED(rv)) {
rv = associatedURL->Equals(pushedURL, &match);
@@ -1797,36 +1812,38 @@ Http2Session::RecvPushPromise(Http2Session *self)
if (NS_FAILED(rv)) {
// Fallback to string equality of origins. This won't be guaranteed to be as
// liberal as we want it to be, but it will at least be safe
match = associatedStream->Origin().Equals(pushedStream->Origin());
match = associatedStream->Origin().Equals(pushedWeak->Origin());
}
if (!match) {
LOG3(("Http2Session::RecvPushPromise %p pushed stream mismatched origin "
"associated origin %s .. pushed origin %s\n", self,
associatedStream->Origin().get(), pushedStream->Origin().get()));
self->CleanupStream(pushedStream, NS_ERROR_FAILURE, REFUSED_STREAM_ERROR);
associatedStream->Origin().get(), pushedWeak->Origin().get()));
self->CleanupStream(pushedWeak, NS_ERROR_FAILURE, REFUSED_STREAM_ERROR);
self->ResetDownstreamState();
return NS_OK;
}
if (pushedStream->TryOnPush()) {
if (static_cast<Http2PushedStream*>(pushedWeak.get())->TryOnPush()) {
LOG3(("Http2Session::RecvPushPromise %p channel implements nsIHttpPushListener "
"stream %p will not be placed into session cache.\n", self, pushedStream));
"stream %p will not be placed into session cache.\n", self, pushedWeak.get()));
} else {
LOG3(("Http2Session::RecvPushPromise %p place stream into session cache\n", self));
if (!cache->RegisterPushedStreamHttp2(key, pushedStream)) {
if (!cache->RegisterPushedStreamHttp2(
key, static_cast<Http2PushedStream*>(pushedWeak.get()))) {
// This only happens if they've already pushed us this item.
LOG3(("Http2Session::RecvPushPromise registerPushedStream Failed\n"));
self->CleanupStream(pushedStream, NS_ERROR_FAILURE, INTERNAL_ERROR);
self->CleanupStream(pushedWeak, NS_ERROR_FAILURE, INTERNAL_ERROR);
self->ResetDownstreamState();
return NS_OK;
}
}
pushedStream->SetHTTPState(Http2Stream::RESERVED_BY_REMOTE);
pushedWeak->SetHTTPState(Http2Stream::RESERVED_BY_REMOTE);
static_assert(Http2Stream::kWorstPriority >= 0,
"kWorstPriority out of range");
uint8_t priorityWeight = (nsISupportsPriority::PRIORITY_LOWEST + 1) -
(Http2Stream::kWorstPriority - Http2Stream::kNormalPriority);
pushedStream->SetPriority(Http2Stream::kWorstPriority);
pushedWeak->SetPriority(Http2Stream::kWorstPriority);
self->GeneratePriority(promisedID, priorityWeight);
self->ResetDownstreamState();
return NS_OK;
+3 -1
View File
@@ -443,12 +443,14 @@ Http2Stream::ParseHttpRequestHeaders(const char *buf,
requestContext->GetSpdyPushCache(&cache);
}
RefPtr<Http2PushedStreamWrapper> pushedStreamWrapper;
Http2PushedStream *pushedStream = nullptr;
// If a push stream is attached to the transaction via onPush, match only with that
// one. This occurs when a push was made with in conjunction with a nsIHttpPushListener
nsHttpTransaction *trans = mTransaction->QueryHttpTransaction();
if (trans && (pushedStream = trans->TakePushedStream())) {
if (trans && (pushedStreamWrapper = trans->TakePushedStream()) &&
(pushedStream = pushedStreamWrapper->GetStream())) {
if (pushedStream->mSession == mSession) {
LOG3(("Pushed Stream match based on OnPush correlation %p", pushedStream));
} else {
+3
View File
@@ -14,6 +14,7 @@
#include "nsAHttpTransaction.h"
#include "nsISupportsPriority.h"
#include "SimpleBuffer.h"
#include "mozilla/WeakPtr.h"
class nsIInputStream;
class nsIOutputStream;
@@ -28,8 +29,10 @@ class Http2Decompressor;
class Http2Stream
: public nsAHttpSegmentReader
, public nsAHttpSegmentWriter
, public SupportsWeakPtr<Http2Stream>
{
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Http2Stream)
NS_DECL_NSAHTTPSEGMENTREADER
NS_DECL_NSAHTTPSEGMENTWRITER
+17 -13
View File
@@ -543,13 +543,14 @@ HttpChannelChild::DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
{
LOG(("HttpChannelChild::DoOnStartRequest [this=%p]\n", this));
// In theory mListener should not be null, but in practice sometimes it is.
MOZ_ASSERT(mListener);
if (!mListener) {
Cancel(NS_ERROR_FAILURE);
return;
nsresult rv;
if (MOZ_LIKELY(mListener)) {
nsCOMPtr<nsIStreamListener> listener(mListener);
rv = listener->OnStartRequest(aRequest, aContext);
} else {
rv = NS_ERROR_UNEXPECTED;
}
nsresult rv = mListener->OnStartRequest(aRequest, aContext);
if (NS_FAILED(rv)) {
Cancel(rv);
return;
@@ -804,9 +805,12 @@ HttpChannelChild::DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
if (mCanceled)
return;
nsresult rv = mListener->OnDataAvailable(aRequest, aContext, aStream, offset, count);
if (NS_FAILED(rv)) {
Cancel(rv);
if (MOZ_LIKELY(mListener)) {
nsCOMPtr<nsIStreamListener> listener(mListener);
nsresult rv = listener->OnDataAvailable(aRequest, aContext, aStream, offset, count);
if (NS_FAILED(rv)) {
Cancel(rv);
}
}
}
@@ -985,11 +989,11 @@ HttpChannelChild::DoOnStopRequest(nsIRequest* aRequest, nsresult aChannelStatus,
MOZ_ASSERT(!mOnStopRequestCalled,
"We should not call OnStopRequest twice");
// In theory mListener should not be null, but in practice sometimes it is.
MOZ_ASSERT(mListener);
if (mListener) {
mListener->OnStopRequest(aRequest, aContext, mStatus);
if (MOZ_LIKELY(mListener)) {
nsCOMPtr<nsIStreamListener> listener(mListener);
listener->OnStopRequest(aRequest, aContext, mStatus);
}
mOnStopRequestCalled = true;
mListener = nullptr;
@@ -912,6 +912,9 @@ nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel,
NS_ENSURE_SUCCESS(rv, rv);
}
// TODO: Bug 1353683
// consider calling SetBlockedRequest in nsCORSListenerProxy::UpdateChannel
//
// Check that the uri is ok to load
rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(mRequestingPrincipal, uri,
+5 -3
View File
@@ -6915,7 +6915,8 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st
if (mListener) {
MOZ_ASSERT(!mOnStartRequestCalled,
"We should not call OnStartRequest twice.");
mListener->OnStartRequest(this, mListenerContext);
nsCOMPtr<nsIStreamListener> listener(mListener);
listener->OnStartRequest(this, mListenerContext);
mOnStartRequestCalled = true;
} else {
NS_WARNING("OnStartRequest skipped because of null listener");
@@ -8100,7 +8101,7 @@ nsHttpChannel::AwaitingCacheCallbacks()
}
void
nsHttpChannel::SetPushedStream(Http2PushedStream *stream)
nsHttpChannel::SetPushedStream(Http2PushedStreamWrapper *stream)
{
MOZ_ASSERT(stream);
MOZ_ASSERT(!mPushedStream);
@@ -8108,7 +8109,8 @@ nsHttpChannel::SetPushedStream(Http2PushedStream *stream)
}
nsresult
nsHttpChannel::OnPush(const nsACString &url, Http2PushedStream *pushedStream)
nsHttpChannel::OnPush(const nsACString &url,
Http2PushedStreamWrapper *pushedStream)
{
MOZ_ASSERT(NS_IsMainThread());
LOG(("nsHttpChannel::OnPush [this=%p]\n", this));
+4 -3
View File
@@ -128,7 +128,8 @@ public:
nsIURI *aProxyURI,
const nsID& aChannelId) override;
nsresult OnPush(const nsACString &uri, Http2PushedStream *pushedStream);
nsresult OnPush(const nsACString &uri,
Http2PushedStreamWrapper *pushedStream);
static bool IsRedirectStatus(uint32_t status);
@@ -456,7 +457,7 @@ private:
nsresult OpenCacheInputStream(nsICacheEntry* cacheEntry, bool startBuffering,
bool checkingAppCacheEntry);
void SetPushedStream(Http2PushedStream *stream);
void SetPushedStream(Http2PushedStreamWrapper *stream);
void MaybeWarnAboutAppCache();
@@ -592,7 +593,7 @@ private:
// Needed for accurate DNS timing
RefPtr<nsDNSPrefetch> mDNSPrefetch;
Http2PushedStream *mPushedStream;
RefPtr<Http2PushedStreamWrapper> mPushedStream;
// True if the channel's principal was found on a phishing, malware, or
// tracking (if tracking protection is enabled) blocklist
bool mLocalBlocklist;
+22 -10
View File
@@ -376,8 +376,12 @@ nsHttpConnectionMgr::VerifyTraffic()
nsresult
nsHttpConnectionMgr::DoShiftReloadConnectionCleanup(nsHttpConnectionInfo *aCI)
{
RefPtr<nsHttpConnectionInfo> ci;
if (aCI) {
ci = aCI->Clone();
}
return PostEvent(&nsHttpConnectionMgr::OnMsgDoShiftReloadConnectionCleanup,
0, aCI);
0, ci);
}
class SpeculativeConnectArgs : public ARefBase
@@ -507,9 +511,13 @@ nsHttpConnectionMgr::UpdateParam(nsParamName name, uint16_t value)
}
nsresult
nsHttpConnectionMgr::ProcessPendingQ(nsHttpConnectionInfo *ci)
nsHttpConnectionMgr::ProcessPendingQ(nsHttpConnectionInfo* aCI)
{
LOG(("nsHttpConnectionMgr::ProcessPendingQ [ci=%s]\n", ci->HashKey().get()));
LOG(("nsHttpConnectionMgr::ProcessPendingQ [ci=%s]\n", aCI->HashKey().get()));
RefPtr<nsHttpConnectionInfo> ci;
if (aCI) {
ci = aCI->Clone();
}
return PostEvent(&nsHttpConnectionMgr::OnMsgProcessPendingQ, 0, ci);
}
@@ -1863,13 +1871,17 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans)
trans->SetPendingTime();
Http2PushedStream *pushedStream = trans->GetPushedStream();
if (pushedStream) {
LOG((" ProcessNewTransaction %p tied to h2 session push %p\n",
trans, pushedStream->Session()));
return pushedStream->Session()->
AddStream(trans, trans->Priority(), false, nullptr) ?
NS_OK : NS_ERROR_UNEXPECTED;
RefPtr<Http2PushedStreamWrapper> pushedStreamWrapper =
trans->GetPushedStream();
if (pushedStreamWrapper) {
Http2PushedStream* pushedStream = pushedStreamWrapper->GetStream();
if (pushedStream) {
LOG((" ProcessNewTransaction %p tied to h2 session push %p\n",
trans, pushedStream->Session()));
return pushedStream->Session()->
AddStream(trans, trans->Priority(), false, nullptr) ?
NS_OK : NS_ERROR_UNEXPECTED;
}
}
nsresult rv = NS_OK;
+1 -1
View File
@@ -2361,7 +2361,7 @@ nsHttpHandler::SpeculativeConnectInternal(nsIURI *aURI,
originAttributes.StripAttributes(OriginAttributes::STRIP_ADDON_ID);
}
auto *ci =
RefPtr<nsHttpConnectionInfo> ci =
new nsHttpConnectionInfo(host, port, EmptyCString(), username, nullptr,
originAttributes, usingSSL);
ci->SetAnonymous(anonymous);
+2 -1
View File
@@ -235,7 +235,8 @@ public:
uint32_t caps = 0)
{
TickleWifi(callbacks);
return mConnMgr->SpeculativeConnect(ci, callbacks, caps);
RefPtr<nsHttpConnectionInfo> clone = ci->Clone();
return mConnMgr->SpeculativeConnect(clone, callbacks, caps);
}
// Alternate Services Maps are main thread only
+10 -8
View File
@@ -136,14 +136,16 @@ public:
nsHttpTransaction *QueryHttpTransaction() override { return this; }
Http2PushedStream *GetPushedStream() { return mPushedStream; }
Http2PushedStream *TakePushedStream()
{
Http2PushedStream *r = mPushedStream;
mPushedStream = nullptr;
return r;
already_AddRefed<Http2PushedStreamWrapper> GetPushedStream() {
//return do_AddRef(mPushedStream); // XXX: add this support to RefPtr.h
RefPtr<Http2PushedStreamWrapper> ref(mPushedStream);
return ref.forget();
}
void SetPushedStream(Http2PushedStream *push) { mPushedStream = push; }
already_AddRefed<Http2PushedStreamWrapper> TakePushedStream() {
return mPushedStream.forget();
}
void SetPushedStream(Http2PushedStreamWrapper* push) { mPushedStream = push; }
uint32_t InitialRwin() const { return mInitialRwin; };
bool ChannelPipeFull() { return mWaitingOnPipeOut; }
@@ -269,7 +271,7 @@ private:
// so far been skipped.
uint32_t mInvalidResponseBytesRead;
Http2PushedStream *mPushedStream;
RefPtr<Http2PushedStreamWrapper> mPushedStream;
uint32_t mInitialRwin;
nsHttpChunkedDecoder *mChunkedDecoder;
+3 -2
View File
@@ -956,8 +956,9 @@ nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL,
const nsAString& aImageReferrerPolicy)
{
nsCOMPtr<nsIURI> baseURI = BaseURIForPreload();
bool isImgSet = false;
nsCOMPtr<nsIURI> uri = mDocument->ResolvePreloadImage(baseURI, aURL, aSrcset,
aSizes);
aSizes, &isImgSet);
if (uri && ShouldPreloadURI(uri)) {
// use document wide referrer policy
mozilla::net::ReferrerPolicy referrerPolicy = mSpeculationReferrerPolicy;
@@ -971,7 +972,7 @@ nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL,
}
}
mDocument->MaybePreLoadImage(uri, aCrossOrigin, referrerPolicy);
mDocument->MaybePreLoadImage(uri, aCrossOrigin, referrerPolicy, isImgSet);
}
}