diff options
37 files changed, 521 insertions, 110 deletions
diff --git a/dom/cache/TypeUtils.cpp b/dom/cache/TypeUtils.cpp index 1af5ee9458..89fe2a62fb 100644 --- a/dom/cache/TypeUtils.cpp +++ b/dom/cache/TypeUtils.cpp @@ -190,7 +190,7 @@ TypeUtils::ToCacheResponseWithoutBody(CacheResponse& aOut, aOut.statusText() = aIn.GetUnfilteredStatusText(); RefPtr<InternalHeaders> headers = aIn.UnfilteredHeaders(); MOZ_DIAGNOSTIC_ASSERT(headers); - if (HasVaryStar(headers)) { + if (aIn.Type() != ResponseType::Opaque && HasVaryStar(headers)) { aRv.ThrowTypeError<MSG_RESPONSE_HAS_VARY_STAR>(); return; } diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index 0510e6898a..8984b71366 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -8,6 +8,7 @@ #include <stdarg.h> +#include "gfxPrefs.h" #include "GLContextTypes.h" #include "GLDefs.h" #include "mozilla/Attributes.h" @@ -1397,6 +1398,7 @@ protected: CheckedUint32 mGeneration; WebGLContextOptions mOptions; + const uint32_t mMaxVertIdsPerDraw = gfxPrefs::WebglMaxVertIDsPerDraw(); bool mInvalidated; bool mCapturedFrameInvalidated; diff --git a/dom/canvas/WebGLContextDraw.cpp b/dom/canvas/WebGLContextDraw.cpp index 6c684b2ff8..a01e38c5c6 100644 --- a/dom/canvas/WebGLContextDraw.cpp +++ b/dom/canvas/WebGLContextDraw.cpp @@ -607,6 +607,12 @@ WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertCount, return; MakeContextCurrent(); + + if (vertCount > mMaxVertIdsPerDraw) {
+ ErrorOutOfMemory(
+ "Context's max vertCount is %u, but %u requested. [webgl.max-vert-ids-per-draw]", mMaxVertIdsPerDraw, vertCount);
+ return;
+ }
bool error = false; ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error); @@ -849,6 +855,12 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei vertCount, GLenum type, return; MakeContextCurrent(); +
+ if (vertCount > mMaxVertIdsPerDraw) {
+ ErrorOutOfMemory(
+ "Context's max vertCount is %u, but %u requested. [webgl.max-vert-ids-per-draw]", mMaxVertIdsPerDraw, vertCount);
+ return;
+ }
bool error = false; ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error); diff --git a/dom/canvas/WebGLShaderValidator.cpp b/dom/canvas/WebGLShaderValidator.cpp index bf2df82f71..7ea9f11a70 100644 --- a/dom/canvas/WebGLShaderValidator.cpp +++ b/dom/canvas/WebGLShaderValidator.cpp @@ -9,6 +9,7 @@ #include "angle/ShaderLang.h" #include "gfxPrefs.h" #include "GLContext.h" +#include "mozilla/gfx/Logging.h" #include "mozilla/Preferences.h" #include "MurmurHash3.h" #include "nsPrintfCString.h" @@ -135,9 +136,13 @@ ShaderOutput(gl::GLContext* gl) case 420: return SH_GLSL_420_CORE_OUTPUT; case 430: return SH_GLSL_430_CORE_OUTPUT; case 440: return SH_GLSL_440_CORE_OUTPUT; - case 450: return SH_GLSL_450_CORE_OUTPUT; default: - MOZ_ASSERT(false, "GFX: Unexpected GLSL version."); + if (version >= 450) { + // "OpenGL 4.6 is also guaranteed to support all previous versions of the + // OpenGL Shading Language back to version 1.10." + return SH_GLSL_450_CORE_OUTPUT; + } + gfxCriticalNote << "Unexpected GLSL version: " << version; } } diff --git a/dom/media/MediaData.cpp b/dom/media/MediaData.cpp index 4852ea486b..9f1205a0e1 100644 --- a/dom/media/MediaData.cpp +++ b/dom/media/MediaData.cpp @@ -7,6 +7,8 @@ #include "MediaInfo.h" #include "VideoUtils.h" #include "ImageContainer.h" +#include "mozilla/layers/SharedRGBImage.h" +#include "YCbCrUtils.h" #include <stdint.h> @@ -89,6 +91,45 @@ ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane) aPlane.mStride > 0 && aPlane.mWidth <= aPlane.mStride; } +static bool ValidateBufferAndPicture(const VideoData::YCbCrBuffer& aBuffer, + const IntRect& aPicture) +{ + // The following situation should never happen unless there is a bug + // in the decoder + if (aBuffer.mPlanes[1].mWidth != aBuffer.mPlanes[2].mWidth || + aBuffer.mPlanes[1].mHeight != aBuffer.mPlanes[2].mHeight) { + NS_ERROR("C planes with different sizes"); + return false; + } + + // The following situations could be triggered by invalid input + if (aPicture.width <= 0 || aPicture.height <= 0) { + // In debug mode, makes the error more noticeable + MOZ_ASSERT(false, "Empty picture rect"); + return false; + } + if (!ValidatePlane(aBuffer.mPlanes[0]) || + !ValidatePlane(aBuffer.mPlanes[1]) || + !ValidatePlane(aBuffer.mPlanes[2])) { + NS_WARNING("Invalid plane size"); + return false; + } + + // Ensure the picture size specified in the headers can be extracted out of + // the frame we've been supplied without indexing out of bounds. + CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width); + CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height); + if (!xLimit.isValid() || xLimit.value() > aBuffer.mPlanes[0].mStride || + !yLimit.isValid() || yLimit.value() > aBuffer.mPlanes[0].mHeight) + { + // The specified picture dimensions can't be contained inside the video + // frame, we'll stomp memory if we try to copy it. Fail. + NS_WARNING("Overflowing picture rect"); + return false; + } + return true; +} + VideoData::VideoData(int64_t aOffset, int64_t aTime, int64_t aDuration, @@ -242,36 +283,7 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo, return v.forget(); } - // The following situation should never happen unless there is a bug - // in the decoder - if (aBuffer.mPlanes[1].mWidth != aBuffer.mPlanes[2].mWidth || - aBuffer.mPlanes[1].mHeight != aBuffer.mPlanes[2].mHeight) { - NS_ERROR("C planes with different sizes"); - return nullptr; - } - - // The following situations could be triggered by invalid input - if (aPicture.width <= 0 || aPicture.height <= 0) { - // In debug mode, makes the error more noticeable - MOZ_ASSERT(false, "Empty picture rect"); - return nullptr; - } - if (!ValidatePlane(aBuffer.mPlanes[0]) || !ValidatePlane(aBuffer.mPlanes[1]) || - !ValidatePlane(aBuffer.mPlanes[2])) { - NS_WARNING("Invalid plane size"); - return nullptr; - } - - // Ensure the picture size specified in the headers can be extracted out of - // the frame we've been supplied without indexing out of bounds. - CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width); - CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height); - if (!xLimit.isValid() || xLimit.value() > aBuffer.mPlanes[0].mStride || - !yLimit.isValid() || yLimit.value() > aBuffer.mPlanes[0].mHeight) - { - // The specified picture dimensions can't be contained inside the video - // frame, we'll stomp memory if we try to copy it. Fail. - NS_WARNING("Overflowing picture rect"); + if (!ValidateBufferAndPicture(aBuffer, aPicture)) { return nullptr; } @@ -307,6 +319,73 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo, /* static */ already_AddRefed<VideoData> +VideoData::CreateAndCopyData(const VideoInfo& aInfo, + ImageContainer* aContainer, + int64_t aOffset, + int64_t aTime, + int64_t aDuration, + const YCbCrBuffer& aBuffer, + const YCbCrBuffer::Plane &aAlphaPlane, + bool aKeyframe, + int64_t aTimecode, + const IntRect& aPicture) +{ + if (!aContainer) { + // Create a dummy VideoData with no image. This gives us something to + // send to media streams if necessary. + RefPtr<VideoData> v(new VideoData(aOffset, + aTime, + aDuration, + aKeyframe, + aTimecode, + aInfo.mDisplay, + 0)); + return v.forget(); + } + + if (!ValidateBufferAndPicture(aBuffer, aPicture)) { + return nullptr; + } + + RefPtr<VideoData> v(new VideoData(aOffset, + aTime, + aDuration, + aKeyframe, + aTimecode, + aInfo.mDisplay, + 0)); + + // Convert from YUVA to BGRA format on the software side. + RefPtr<layers::SharedRGBImage> videoImage = + aContainer->CreateSharedRGBImage(); + v->mImage = videoImage; + + if (!v->mImage) { + return nullptr; + } + if (!videoImage->Allocate(IntSize(aBuffer.mPlanes[0].mWidth, + aBuffer.mPlanes[0].mHeight), + SurfaceFormat::B8G8R8A8)) { + return nullptr; + } + uint8_t* argb_buffer = videoImage->GetBuffer(); + IntSize size = videoImage->GetSize(); + + // The naming convention for libyuv and associated utils is word-order. + // The naming convention in the gfx stack is byte-order. + ConvertYCbCrAToARGB(aBuffer.mPlanes[0].mData, + aBuffer.mPlanes[1].mData, + aBuffer.mPlanes[2].mData, + aAlphaPlane.mData, + aBuffer.mPlanes[0].mStride, aBuffer.mPlanes[1].mStride, + argb_buffer, size.width * 4, + size.width, size.height); + + return v.forget(); +} + +/* static */ +already_AddRefed<VideoData> VideoData::CreateFromImage(const VideoInfo& aInfo, int64_t aOffset, int64_t aTime, @@ -340,6 +419,15 @@ MediaRawData::MediaRawData(const uint8_t* aData, size_t aSize) { } +MediaRawData::MediaRawData(const uint8_t* aData, size_t aSize, + const uint8_t* aAlphaData, size_t aAlphaSize) + : MediaData(RAW_DATA, 0) + , mCrypto(mCryptoInternal) + , mBuffer(aData, aSize) + , mAlphaBuffer(aAlphaData, aAlphaSize) +{ +} + already_AddRefed<MediaRawData> MediaRawData::Clone() const { @@ -356,6 +444,9 @@ MediaRawData::Clone() const if (!s->mBuffer.Append(mBuffer.Data(), mBuffer.Length())) { return nullptr; } + if (!s->mAlphaBuffer.Append(mAlphaBuffer.Data(), mAlphaBuffer.Length())) { + return nullptr; + } return s.forget(); } diff --git a/dom/media/MediaData.h b/dom/media/MediaData.h index dc93c84872..02a7162f42 100644 --- a/dom/media/MediaData.h +++ b/dom/media/MediaData.h @@ -474,6 +474,17 @@ public: int64_t aTimecode, const IntRect& aPicture); + static already_AddRefed<VideoData> CreateAndCopyData(const VideoInfo& aInfo, + ImageContainer* aContainer, + int64_t aOffset, + int64_t aTime, + int64_t aDuration, + const YCbCrBuffer &aBuffer, + const YCbCrBuffer::Plane &aAlphaPlane, + bool aKeyframe, + int64_t aTimecode, + const IntRect& aPicture); + static already_AddRefed<VideoData> CreateAndCopyIntoTextureClient(const VideoInfo& aInfo, int64_t aOffset, int64_t aTime, @@ -622,15 +633,22 @@ private: class MediaRawData : public MediaData { public: MediaRawData(); - MediaRawData(const uint8_t* aData, size_t mSize); + MediaRawData(const uint8_t* aData, size_t aSize); + MediaRawData(const uint8_t* aData, size_t aSize, + const uint8_t* aAlphaData, size_t aAlphaSize); // Pointer to data or null if not-yet allocated const uint8_t* Data() const { return mBuffer.Data(); } + // Pointer to alpha data or null if not-yet allocated + const uint8_t* AlphaData() const { return mAlphaBuffer.Data(); } // Size of buffer. size_t Size() const { return mBuffer.Length(); } + size_t AlphaSize() const { return mAlphaBuffer.Length(); } size_t ComputedSizeOfIncludingThis() const { - return sizeof(*this) + mBuffer.ComputedSizeOfExcludingThis(); + return sizeof(*this) + + mBuffer.ComputedSizeOfExcludingThis() + + mAlphaBuffer.ComputedSizeOfExcludingThis(); } // Access the buffer as a Span. operator Span<const uint8_t>() { return MakeSpan(Data(), Size()); } @@ -661,6 +679,7 @@ protected: private: friend class MediaRawDataWriter; AlignedByteBuffer mBuffer; + AlignedByteBuffer mAlphaBuffer; CryptoSample mCryptoInternal; MediaRawData(const MediaRawData&); // Not implemented }; diff --git a/dom/media/MediaInfo.h b/dom/media/MediaInfo.h index 2ddaf5a43f..62477cabd8 100644 --- a/dom/media/MediaInfo.h +++ b/dom/media/MediaInfo.h @@ -215,6 +215,7 @@ public: , mRotation(aOther.mRotation) , mBitDepth(aOther.mBitDepth) , mImageRect(aOther.mImageRect) + , mAlphaPresent(aOther.mAlphaPresent) { } @@ -238,6 +239,16 @@ public: return MakeUnique<VideoInfo>(*this); } + void SetAlpha(bool aAlphaPresent) + { + mAlphaPresent = aAlphaPresent; + } + + bool HasAlpha() const + { + return mAlphaPresent; + } + nsIntRect ImageRect() const { if (mImageRect.width < 0 || mImageRect.height < 0) { @@ -312,6 +323,9 @@ private: // mImage may be cropped; currently only used with the WebM container. // A negative width or height indicate that no cropping is to occur. nsIntRect mImageRect; + + // Indicates whether or not frames may contain alpha information. + bool mAlphaPresent = false; }; class AudioInfo : public TrackInfo { diff --git a/dom/media/mediasource/MediaSourceDemuxer.cpp b/dom/media/mediasource/MediaSourceDemuxer.cpp index cace222167..4c8f1d0c94 100644 --- a/dom/media/mediasource/MediaSourceDemuxer.cpp +++ b/dom/media/mediasource/MediaSourceDemuxer.cpp @@ -62,7 +62,7 @@ MediaSourceDemuxer::AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes RefPtr<MediaSourceDecoder::ResourceSizes> sizes = aSizes; nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([self, sizes] () { - for (TrackBuffersManager* manager : self->mSourceBuffers) { + for (const RefPtr<TrackBuffersManager>& manager : self->mSourceBuffers) { manager->AddSizeOfResources(sizes); } }); @@ -171,42 +171,45 @@ MediaSourceDemuxer::GetCrypto() } void -MediaSourceDemuxer::AttachSourceBuffer(TrackBuffersManager* aSourceBuffer) +MediaSourceDemuxer::AttachSourceBuffer( + RefPtr<TrackBuffersManager>& aSourceBuffer) { - nsCOMPtr<nsIRunnable> task = - NewRunnableMethod<TrackBuffersManager*>( + nsCOMPtr<nsIRunnable> task = NewRunnableMethod<RefPtr<TrackBuffersManager>&&>( this, &MediaSourceDemuxer::DoAttachSourceBuffer, aSourceBuffer); GetTaskQueue()->Dispatch(task.forget()); } void -MediaSourceDemuxer::DoAttachSourceBuffer(mozilla::TrackBuffersManager* aSourceBuffer) +MediaSourceDemuxer::DoAttachSourceBuffer( + RefPtr<mozilla::TrackBuffersManager>&& aSourceBuffer) { MOZ_ASSERT(OnTaskQueue()); - mSourceBuffers.AppendElement(aSourceBuffer); + mSourceBuffers.AppendElement(Move(aSourceBuffer)); ScanSourceBuffersForContent(); } void -MediaSourceDemuxer::DetachSourceBuffer(TrackBuffersManager* aSourceBuffer) +MediaSourceDemuxer::DetachSourceBuffer( + RefPtr<TrackBuffersManager>& aSourceBuffer) { - nsCOMPtr<nsIRunnable> task = - NewRunnableMethod<TrackBuffersManager*>( - this, &MediaSourceDemuxer::DoDetachSourceBuffer, - aSourceBuffer); + RefPtr<MediaSourceDemuxer> self = this; + nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction( + [self, aSourceBuffer]() { + self->DoDetachSourceBuffer(aSourceBuffer); + }); GetTaskQueue()->Dispatch(task.forget()); } void -MediaSourceDemuxer::DoDetachSourceBuffer(TrackBuffersManager* aSourceBuffer) +MediaSourceDemuxer::DoDetachSourceBuffer( + const RefPtr<TrackBuffersManager>& aSourceBuffer) { MOZ_ASSERT(OnTaskQueue()); - for (uint32_t i = 0; i < mSourceBuffers.Length(); i++) { - if (mSourceBuffers[i].get() == aSourceBuffer) { - mSourceBuffers.RemoveElementAt(i); - } - } + mSourceBuffers.RemoveElementsBy( + [&aSourceBuffer](const RefPtr<TrackBuffersManager> aLinkedSourceBuffer) { + return aLinkedSourceBuffer == aSourceBuffer; + }); if (aSourceBuffer == mAudioTrack) { mAudioTrack = nullptr; } @@ -230,7 +233,7 @@ MediaSourceDemuxer::GetTrackInfo(TrackType aTrack) } } -TrackBuffersManager* +RefPtr<TrackBuffersManager> MediaSourceDemuxer::GetManager(TrackType aTrack) { MonitorAutoLock mon(mMonitor); diff --git a/dom/media/mediasource/MediaSourceDemuxer.h b/dom/media/mediasource/MediaSourceDemuxer.h index e9db46196c..1518364c33 100644 --- a/dom/media/mediasource/MediaSourceDemuxer.h +++ b/dom/media/mediasource/MediaSourceDemuxer.h @@ -45,8 +45,8 @@ public: void NotifyDataArrived() override; /* interface for TrackBuffersManager */ - void AttachSourceBuffer(TrackBuffersManager* aSourceBuffer); - void DetachSourceBuffer(TrackBuffersManager* aSourceBuffer); + void AttachSourceBuffer(RefPtr<TrackBuffersManager>& aSourceBuffer); + void DetachSourceBuffer(RefPtr<TrackBuffersManager>& aSourceBuffer); AutoTaskQueue* GetTaskQueue() { return mTaskQueue; } // Returns a string describing the state of the MediaSource internal @@ -64,10 +64,10 @@ private: // Scan source buffers and update information. bool ScanSourceBuffersForContent(); RefPtr<InitPromise> AttemptInit(); - TrackBuffersManager* GetManager(TrackInfo::TrackType aType); + RefPtr<TrackBuffersManager> GetManager(TrackInfo::TrackType aType); TrackInfo* GetTrackInfo(TrackInfo::TrackType); - void DoAttachSourceBuffer(TrackBuffersManager* aSourceBuffer); - void DoDetachSourceBuffer(TrackBuffersManager* aSourceBuffer); + void DoAttachSourceBuffer(RefPtr<TrackBuffersManager>&& aSourceBuffer); + void DoDetachSourceBuffer(const RefPtr<TrackBuffersManager>& aSourceBuffer); bool OnTaskQueue() { return !GetTaskQueue() || GetTaskQueue()->IsCurrentThreadIn(); diff --git a/dom/media/mediasource/SourceBuffer.cpp b/dom/media/mediasource/SourceBuffer.cpp index 26ea937077..0bdfbfcf23 100644 --- a/dom/media/mediasource/SourceBuffer.cpp +++ b/dom/media/mediasource/SourceBuffer.cpp @@ -281,7 +281,7 @@ SourceBuffer::Detach() if (mTrackBuffersManager) { mTrackBuffersManager->Detach(); mMediaSource->GetDecoder()->GetDemuxer()->DetachSourceBuffer( - mTrackBuffersManager.get()); + mTrackBuffersManager); } mTrackBuffersManager = nullptr; mMediaSource = nullptr; @@ -321,7 +321,7 @@ SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType) SetMode(SourceBufferAppendMode::Segments, dummy); } mMediaSource->GetDecoder()->GetDemuxer()->AttachSourceBuffer( - mTrackBuffersManager.get()); + mTrackBuffersManager); } SourceBuffer::~SourceBuffer() diff --git a/dom/media/platforms/agnostic/VPXDecoder.cpp b/dom/media/platforms/agnostic/VPXDecoder.cpp index 007ead0c7d..00cf7d85cc 100644 --- a/dom/media/platforms/agnostic/VPXDecoder.cpp +++ b/dom/media/platforms/agnostic/VPXDecoder.cpp @@ -35,6 +35,38 @@ static VPXDecoder::Codec MimeTypeToCodec(const nsACString& aMimeType) return VPXDecoder::Codec::Unknown; } +static nsresult +InitContext(vpx_codec_ctx_t* aCtx, + const VideoInfo& aInfo, + const VPXDecoder::Codec aCodec) +{ + int decode_threads = 2; + + vpx_codec_iface_t* dx = nullptr; + if (aCodec == VPXDecoder::Codec::VP8) { + dx = vpx_codec_vp8_dx(); + } + else if (aCodec == VPXDecoder::Codec::VP9) { + dx = vpx_codec_vp9_dx(); + if (aInfo.mDisplay.width >= 2048) { + decode_threads = 8; + } + else if (aInfo.mDisplay.width >= 1024) { + decode_threads = 4; + } + } + decode_threads = std::min(decode_threads, PR_GetNumberOfProcessors()); + + vpx_codec_dec_cfg_t config; + config.threads = decode_threads; + config.w = config.h = 0; // set after decode + + if (!dx || vpx_codec_dec_init(aCtx, dx, &config, 0)) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + VPXDecoder::VPXDecoder(const CreateDecoderParams& aParams) : mImageContainer(aParams.mImageContainer) , mTaskQueue(aParams.mTaskQueue) @@ -45,6 +77,7 @@ VPXDecoder::VPXDecoder(const CreateDecoderParams& aParams) { MOZ_COUNT_CTOR(VPXDecoder); PodZero(&mVPX); + PodZero(&mVPXAlpha); } VPXDecoder::~VPXDecoder() @@ -56,34 +89,24 @@ void VPXDecoder::Shutdown() { vpx_codec_destroy(&mVPX); + vpx_codec_destroy(&mVPXAlpha); } RefPtr<MediaDataDecoder::InitPromise> VPXDecoder::Init() { - int decode_threads = 2; - - vpx_codec_iface_t* dx = nullptr; - if (mCodec == Codec::VP8) { - dx = vpx_codec_vp8_dx(); - } else if (mCodec == Codec::VP9) { - dx = vpx_codec_vp9_dx(); - if (mInfo.mDisplay.width >= 2048) { - decode_threads = 8; - } else if (mInfo.mDisplay.width >= 1024) { - decode_threads = 4; - } + if (NS_FAILED(InitContext(&mVPX, mInfo, mCodec))) { + return VPXDecoder::InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, + __func__); } - decode_threads = std::min(decode_threads, PR_GetNumberOfProcessors()); - - vpx_codec_dec_cfg_t config; - config.threads = decode_threads; - config.w = config.h = 0; // set after decode - - if (!dx || vpx_codec_dec_init(&mVPX, dx, &config, 0)) { - return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); + if (mInfo.HasAlpha()) { + if (NS_FAILED(InitContext(&mVPXAlpha, mInfo, mCodec))) { + return VPXDecoder::InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, + __func__); + } } - return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__); + return VPXDecoder::InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, + __func__); } void @@ -115,14 +138,27 @@ VPXDecoder::DoDecode(MediaRawData* aSample) RESULT_DETAIL("VPX error: %s", vpx_codec_err_to_string(r))); } - vpx_codec_iter_t iter = nullptr; - vpx_image_t *img; + vpx_codec_iter_t iter = nullptr; + vpx_image_t *img; + vpx_image_t *img_alpha = nullptr; + bool alpha_decoded = false; while ((img = vpx_codec_get_frame(&mVPX, &iter))) { NS_ASSERTION(img->fmt == VPX_IMG_FMT_I420 || img->fmt == VPX_IMG_FMT_I444, "WebM image format not I420 or I444"); - + NS_ASSERTION(!alpha_decoded, + "Multiple frames per packet that contains alpha"); + + if (aSample->AlphaSize() > 0) { + if(!alpha_decoded){ + MediaResult rv = DecodeAlpha(&img_alpha, aSample); + if (NS_FAILED(rv)) { + return(rv); + } + alpha_decoded = true; + } + } // Chroma shifts are rounded down as per the decoding examples in the SDK VideoData::YCbCrBuffer b; b.mPlanes[0].mData = img->planes[0]; @@ -174,17 +210,38 @@ VPXDecoder::DoDecode(MediaRawData* aSample) }(); // TODO: need a newer libvpx to support full color range - RefPtr<VideoData> v = - VideoData::CreateAndCopyData(mInfo, - mImageContainer, - aSample->mOffset, - aSample->mTime, - aSample->mDuration, - b, - aSample->mKeyframe, - aSample->mTimecode, - mInfo.ScaledImageRect(img->d_w, - img->d_h)); + RefPtr<VideoData> v; + if (!img_alpha) { + v = VideoData::CreateAndCopyData(mInfo, + mImageContainer, + aSample->mOffset, + aSample->mTime, + aSample->mDuration, + b, + aSample->mKeyframe, + aSample->mTimecode, + mInfo.ScaledImageRect(img->d_w, + img->d_h)); + } else { + VideoData::YCbCrBuffer::Plane alpha_plane; + alpha_plane.mData = img_alpha->planes[0]; + alpha_plane.mStride = img_alpha->stride[0]; + alpha_plane.mHeight = img_alpha->d_h; + alpha_plane.mWidth = img_alpha->d_w; + alpha_plane.mOffset = alpha_plane.mSkip = 0; + v = VideoData::CreateAndCopyData(mInfo, + mImageContainer, + aSample->mOffset, + aSample->mTime, + aSample->mDuration, + b, + alpha_plane, + aSample->mKeyframe, + aSample->mTimecode, + mInfo.ScaledImageRect(img->d_w, + img->d_h)); + + } if (!v) { LOG("Image allocation error source %ldx%ld display %ldx%ld picture %ldx%ld", @@ -234,6 +291,32 @@ VPXDecoder::Drain() mTaskQueue->Dispatch(NewRunnableMethod(this, &VPXDecoder::ProcessDrain)); } +MediaResult +VPXDecoder::DecodeAlpha(vpx_image_t** aImgAlpha, + MediaRawData* aSample) +{ + vpx_codec_err_t r = vpx_codec_decode(&mVPXAlpha, + aSample->AlphaData(), + aSample->AlphaSize(), + nullptr, + 0); + if (r) { + LOG("VPX decode alpha error: %s", vpx_codec_err_to_string(r)); + return MediaResult( + NS_ERROR_DOM_MEDIA_DECODE_ERR, + RESULT_DETAIL("VPX decode alpha error: %s", vpx_codec_err_to_string(r))); + } + + vpx_codec_iter_t iter = nullptr; + + *aImgAlpha = vpx_codec_get_frame(&mVPXAlpha, &iter); + NS_ASSERTION((*aImgAlpha)->fmt == VPX_IMG_FMT_I420 || + (*aImgAlpha)->fmt == VPX_IMG_FMT_I444, + "WebM image format not I420 or I444"); + + return NS_OK; +} + /* static */ bool VPXDecoder::IsVPX(const nsACString& aMimeType, uint8_t aCodecMask) diff --git a/dom/media/platforms/agnostic/VPXDecoder.h b/dom/media/platforms/agnostic/VPXDecoder.h index f7e63e3a92..25d9bc1d33 100644 --- a/dom/media/platforms/agnostic/VPXDecoder.h +++ b/dom/media/platforms/agnostic/VPXDecoder.h @@ -57,6 +57,8 @@ private: void ProcessDecode(MediaRawData* aSample); MediaResult DoDecode(MediaRawData* aSample); void ProcessDrain(); + MediaResult DecodeAlpha(vpx_image_t** aImgAlpha, + MediaRawData* aSample); const RefPtr<ImageContainer> mImageContainer; const RefPtr<TaskQueue> mTaskQueue; @@ -66,6 +68,9 @@ private: // VPx decoder state vpx_codec_ctx_t mVPX; + // VPx alpha decoder state + vpx_codec_ctx_t mVPXAlpha; + const VideoInfo& mInfo; const Codec mCodec; diff --git a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h index c27f61aad9..95b156ff96 100644 --- a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h +++ b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h @@ -32,6 +32,13 @@ public: already_AddRefed<MediaDataDecoder> CreateVideoDecoder(const CreateDecoderParams& aParams) override { + // Temporary - forces use of VPXDecoder when alpha is present. + // Bug 1263836 will handle alpha scenario once implemented. It will shift + // the check for alpha to PDMFactory but not itself remove the need for a + // check. + if (aParams.VideoConfig().HasAlpha()) { + return nullptr; + } RefPtr<MediaDataDecoder> decoder = new FFmpegVideoDecoder<V>(mLib, aParams.mTaskQueue, diff --git a/dom/media/platforms/wmf/WMFDecoderModule.cpp b/dom/media/platforms/wmf/WMFDecoderModule.cpp index 98412a80a2..46e78fb17f 100644 --- a/dom/media/platforms/wmf/WMFDecoderModule.cpp +++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp @@ -83,6 +83,14 @@ WMFDecoderModule::Startup() already_AddRefed<MediaDataDecoder> WMFDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams) { + // Temporary - forces use of VPXDecoder when alpha is present. + // Bug 1263836 will handle alpha scenario once implemented. It will shift + // the check for alpha to PDMFactory but not itself remove the need for a + // check. + if (aParams.VideoConfig().HasAlpha()) { + return nullptr; + } + nsAutoPtr<WMFVideoMFTManager> manager( new WMFVideoMFTManager(aParams.VideoConfig(), aParams.mKnowsCompositor, diff --git a/dom/media/webm/WebMDemuxer.cpp b/dom/media/webm/WebMDemuxer.cpp index 090229365e..1009fedc69 100644 --- a/dom/media/webm/WebMDemuxer.cpp +++ b/dom/media/webm/WebMDemuxer.cpp @@ -378,6 +378,7 @@ WebMDemuxer::ReadMetadata() mInfo.mVideo.mDisplay = displaySize; mInfo.mVideo.mImage = frameSize; mInfo.mVideo.SetImageRect(pictureRect); + mInfo.mVideo.SetAlpha(params.alpha_mode); switch (params.stereo_mode) { case NESTEGG_VIDEO_MONO: @@ -656,6 +657,21 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl WEBM_DEBUG("nestegg_packet_data failed r=%d", r); return NS_ERROR_DOM_MEDIA_DEMUXER_ERR; } + unsigned char* alphaData; + size_t alphaLength = 0; + // Check packets for alpha information if file has declared alpha frames + // may be present. + if (mInfo.mVideo.HasAlpha()) { + r = nestegg_packet_additional_data(holder->Packet(), + 1, + &alphaData, + &alphaLength); + if (r == -1) { + WEBM_DEBUG( + "nestegg_packet_additional_data failed to retrieve alpha data r=%d", + r); + } + } bool isKeyframe = false; if (aType == TrackInfo::kAudioTrack) { isKeyframe = true; @@ -713,10 +729,19 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl WEBM_DEBUG("push sample tstamp: %ld next_tstamp: %ld length: %ld kf: %d", tstamp, next_tstamp, length, isKeyframe); - RefPtr<MediaRawData> sample = new MediaRawData(data, length); - if (length && !sample->Data()) { - // OOM. - return NS_ERROR_OUT_OF_MEMORY; + RefPtr<MediaRawData> sample; + if (mInfo.mVideo.HasAlpha() && alphaLength != 0) { + sample = new MediaRawData(data, length, alphaData, alphaLength); + if (length && !sample->Data() || (alphaLength && !sample->AlphaData())) { + // OOM. + return NS_ERROR_OUT_OF_MEMORY; + } + } else { + sample = new MediaRawData(data, length); + if (length && !sample->Data()) { + // OOM. + return NS_ERROR_OUT_OF_MEMORY; + } } sample->mTimecode = tstamp; sample->mTime = tstamp; diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 51ab67f708..98f153ea89 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -241,6 +241,7 @@ private: WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { nsresult rv = mWrappedRunnable->Run(); + mWrappedRunnable = nullptr; if (NS_FAILED(rv)) { if (!JS_IsExceptionPending(aCx)) { Throw(aCx, rv); @@ -259,6 +260,7 @@ private: MOZ_ASSERT(cancelable); // We checked this earlier! rv = cancelable->Cancel(); nsresult rv2 = WorkerRunnable::Cancel(); + mWrappedRunnable = nullptr; return NS_FAILED(rv) ? rv : rv2; } }; diff --git a/gfx/layers/ipc/SharedRGBImage.cpp b/gfx/layers/ipc/SharedRGBImage.cpp index bb3bb968cd..2db2ef105a 100644 --- a/gfx/layers/ipc/SharedRGBImage.cpp +++ b/gfx/layers/ipc/SharedRGBImage.cpp @@ -106,7 +106,32 @@ SharedRGBImage::GetTextureClient(KnowsCompositor* aForwarder) already_AddRefed<gfx::SourceSurface> SharedRGBImage::GetAsSourceSurface() { - return nullptr; + NS_ASSERTION(NS_IsMainThread(), "Must be main thread"); + + if (mSourceSurface) { + RefPtr<gfx::SourceSurface> surface(mSourceSurface); + return surface.forget(); + } + + RefPtr<gfx::SourceSurface> surface; + { + // We are 'borrowing' the DrawTarget and retaining a permanent reference to + // the underlying data (via the surface). It is in this instance since we + // know that the TextureClient is always wrapping a BufferTextureData and + // therefore it won't go away underneath us. + BufferTextureData* decoded_buffer = + mTextureClient->GetInternalData()->AsBufferTextureData(); + RefPtr<gfx::DrawTarget> drawTarget = decoded_buffer->BorrowDrawTarget(); + + if (!drawTarget) { + return nullptr; + } + + surface = drawTarget->Snapshot(); + } + + mSourceSurface = surface; + return surface.forget(); } } // namespace layers diff --git a/gfx/layers/ipc/SharedRGBImage.h b/gfx/layers/ipc/SharedRGBImage.h index 2c6009c19c..7122b27bc4 100644 --- a/gfx/layers/ipc/SharedRGBImage.h +++ b/gfx/layers/ipc/SharedRGBImage.h @@ -51,6 +51,7 @@ private: gfx::IntSize mSize; RefPtr<ImageClient> mCompositable; RefPtr<TextureClient> mTextureClient; + nsCountedRef<nsMainThreadSourceSurfaceRef> mSourceSurface; }; } // namespace layers diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index 5dfb742077..3c9fef7d16 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -597,7 +597,8 @@ private: DECL_GFX_PREF(Once, "webgl.force-layers-readback", WebGLForceLayersReadback, bool, false); DECL_GFX_PREF(Live, "webgl.lose-context-on-memory-pressure", WebGLLoseContextOnMemoryPressure, bool, false); DECL_GFX_PREF(Live, "webgl.max-warnings-per-context", WebGLMaxWarningsPerContext, uint32_t, 32); - DECL_GFX_PREF(Live, "webgl.max-size-per-texture-mb", WebGLMaxSizePerTextureMB, uint32_t, 1024); + DECL_GFX_PREF(Live, "webgl.max-size-per-texture-mb", WebGLMaxSizePerTextureMB, uint32_t, 1024); + DECL_GFX_PREF(Live, "webgl.max-vert-ids-per-draw", WebglMaxVertIDsPerDraw, uint32_t, 30*1000*1000); DECL_GFX_PREF(Live, "webgl.min_capability_mode", WebGLMinCapabilityMode, bool, false); DECL_GFX_PREF(Live, "webgl.msaa-force", WebGLForceMSAA, bool, false); DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false); diff --git a/gfx/ycbcr/YCbCrUtils.cpp b/gfx/ycbcr/YCbCrUtils.cpp index f5a4353e2f..0f9c2c8ebc 100644 --- a/gfx/ycbcr/YCbCrUtils.cpp +++ b/gfx/ycbcr/YCbCrUtils.cpp @@ -155,5 +155,26 @@ ConvertYCbCrToRGB(const layers::PlanarYCbCrData& aData, } } +void +ConvertYCbCrAToARGB(const uint8_t* aSrcY, + const uint8_t* aSrcU, + const uint8_t* aSrcV, + const uint8_t* aSrcA, + int aSrcStrideYA, int aSrcStrideUV, + uint8_t* aDstARGB, int aDstStrideARGB, + int aWidth, int aHeight) { + + ConvertYCbCrAToARGB32(aSrcY, + aSrcU, + aSrcV, + aSrcA, + aDstARGB, + aWidth, + aHeight, + aSrcStrideYA, + aSrcStrideUV, + aDstStrideARGB); +} + } // namespace gfx } // namespace mozilla diff --git a/gfx/ycbcr/YCbCrUtils.h b/gfx/ycbcr/YCbCrUtils.h index 1cd2e1c4fd..dcc7b5e9aa 100644 --- a/gfx/ycbcr/YCbCrUtils.h +++ b/gfx/ycbcr/YCbCrUtils.h @@ -24,6 +24,17 @@ ConvertYCbCrToRGB(const layers::PlanarYCbCrData& aData, unsigned char* aDestBuffer, int32_t aStride); +// Currently this function only has support for I420 type. +void +ConvertYCbCrAToARGB(const uint8_t* aSrcY, + const uint8_t* aSrcU, + const uint8_t* aSrcV, + const uint8_t* aSrcA, + int aSrcStrideYA, int aSrcStrideUV, + uint8_t* aDstARGB, int aDstStrideARGB, + int aWidth, int aHeight); + + } // namespace gfx } // namespace mozilla diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp index d3a8c53312..89f6dcfa06 100644 --- a/gfx/ycbcr/yuv_convert.cpp +++ b/gfx/ycbcr/yuv_convert.cpp @@ -550,6 +550,27 @@ void ScaleYCbCrToRGB32_deprecated(const uint8_t* y_buf, if (has_mmx) EMMS(); } +void ConvertYCbCrAToARGB32(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + const uint8_t* a_buf, + uint8_t* argb_buf, + int pic_width, + int pic_height, + int ya_pitch, + int uv_pitch, + int argb_pitch) { + + // The downstream graphics stack expects an attenuated input, hence why the + // attenuation parameter is set. + DebugOnly<int> err = libyuv::I420AlphaToARGB(y_buf, ya_pitch, + u_buf, uv_pitch, + v_buf, uv_pitch, + a_buf, ya_pitch, + argb_buf, argb_pitch, + pic_width, pic_height, 1); + MOZ_ASSERT(!err); +} } // namespace gfx } // namespace mozilla diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h index 108e14b679..2e85ada0a3 100644 --- a/gfx/ycbcr/yuv_convert.h +++ b/gfx/ycbcr/yuv_convert.h @@ -106,6 +106,18 @@ void ScaleYCbCrToRGB32_deprecated(const uint8_t* yplane, Rotate view_rotate, ScaleFilter filter); +void ConvertYCbCrAToARGB32(const uint8_t* yplane, + const uint8_t* uplane, + const uint8_t* vplane, + const uint8_t* aplane, + uint8_t* argbframe, + int pic_width, + int pic_height, + int yastride, + int uvstride, + int argbstride); + + } // namespace gfx } // namespace mozilla diff --git a/layout/media/symbols.def.in b/layout/media/symbols.def.in index 2ad49cbfcf..140d8e7480 100644 --- a/layout/media/symbols.def.in +++ b/layout/media/symbols.def.in @@ -9,6 +9,7 @@ nestegg_duration nestegg_free_packet nestegg_init nestegg_offset_seek +nestegg_packet_additional_data nestegg_packet_count nestegg_packet_discard_padding nestegg_packet_data diff --git a/layout/reftests/webm-video/reftest.list b/layout/reftests/webm-video/reftest.list index 91532af2bb..a178f3e886 100644 --- a/layout/reftests/webm-video/reftest.list +++ b/layout/reftests/webm-video/reftest.list @@ -32,6 +32,7 @@ random == poster-12.html poster-ref-blue140x100.html == poster-13.html poster-ref-blue400x300.html == poster-15.html poster-ref-green70x30.html random-if(winWidget) random-if(cocoaWidget) == bug686957.html bug686957-ref.html # bug 922951 for OS X +== webm-alpha.html webm-alpha-ref.html # Tests for <video src> with 'object-fit' & 'object-position': # These tests should be very similar to tests in our w3c-css/submitted/images3 diff --git a/layout/reftests/webm-video/webm-alpha-ref.html b/layout/reftests/webm-video/webm-alpha-ref.html new file mode 100644 index 0000000000..6675a23a13 --- /dev/null +++ b/layout/reftests/webm-video/webm-alpha-ref.html @@ -0,0 +1,5 @@ +<!DOCTYPE HTML>
+<html>
+<body style="background:black;">
+</body>
+</html>
diff --git a/layout/reftests/webm-video/webm-alpha.html b/layout/reftests/webm-video/webm-alpha.html new file mode 100644 index 0000000000..8c613b473d --- /dev/null +++ b/layout/reftests/webm-video/webm-alpha.html @@ -0,0 +1,10 @@ +<!DOCTYPE HTML>
+<html>
+<body style="background:black;">
+<!--
+ Test that if a WebM video has an alpha channel, it is displayed correctly.
+-->
+<video src="webm-alpha.webm">
+</video>
+</body>
+</html>
diff --git a/layout/reftests/webm-video/webm-alpha.webm b/layout/reftests/webm-video/webm-alpha.webm Binary files differnew file mode 100644 index 0000000000..b6fe4d7b68 --- /dev/null +++ b/layout/reftests/webm-video/webm-alpha.webm diff --git a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp index 3b485372f2..b361ecac55 100644 --- a/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp +++ b/media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp @@ -528,10 +528,16 @@ WebrtcGmpVideoEncoder::Terminated() { LOGD(("GMP Encoder Terminated: %p", (void *)this)); - mGMP->Close(); + GMPVideoEncoderProxy* gmp(mGMP); mGMP = nullptr; mHost = nullptr; mInitting = false; + + if (gmp) { + // Do this last, since this could cause us to be destroyed + gmp->Close(); + } + // Could now notify that it's dead } diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 0f3fa7c85c..f2a53ab720 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4263,6 +4263,7 @@ pref("webgl.can-lose-context-in-foreground", true); pref("webgl.restore-context-when-visible", true); pref("webgl.max-warnings-per-context", 32); pref("webgl.max-size-per-texture-mb", 1024); +pref("webgl.max-vert-ids-per-draw", 30000000); pref("webgl.enable-draft-extensions", false); pref("webgl.enable-privileged-extensions", false); pref("webgl.bypass-shader-validation", false); diff --git a/netwerk/cookie/nsCookieService.cpp b/netwerk/cookie/nsCookieService.cpp index 2c8a5612f3..2549ffaccb 100644 --- a/netwerk/cookie/nsCookieService.cpp +++ b/netwerk/cookie/nsCookieService.cpp @@ -3329,7 +3329,8 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, - 0x1F, /* 0x20, */ 0x00 }; + 0x1F, /* 0x20, */ 0x3B, 0x3D, 0x7F, + 0x00 }; if (cookieAttributes.name.FindCharInSet(illegalNameCharacters, 0) != -1) { COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader, "invalid name character"); return newCookie; diff --git a/view/nsView.cpp b/view/nsView.cpp index 8f509cadeb..2c2768a178 100644 --- a/view/nsView.cpp +++ b/view/nsView.cpp @@ -695,7 +695,10 @@ nsresult nsView::AttachToTopLevelWidget(nsIWidget* aWidget) mWindow = aWidget; mWindow->SetAttachedWidgetListener(this); - mWindow->EnableDragDrop(true); + if (mWindow->WindowType() != eWindowType_invisible) { + nsresult rv = mWindow->AsyncEnableDragDrop(true); + NS_ENSURE_SUCCESS(rv, rv); + } mWidgetIsTopLevel = true; // Refresh the view bounds diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index d3cdf72cfc..c72f0364bc 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -2133,6 +2133,16 @@ nsBaseWidget::UpdateSynthesizedTouchState(MultiTouchInput* aState, return inputToDispatch; } +nsresult +nsBaseWidget::AsyncEnableDragDrop(bool aEnable) +{ + RefPtr<nsBaseWidget> kungFuDeathGrip = this; + return NS_IdleDispatchToCurrentThread( + NS_NewRunnableFunction([this, aEnable, kungFuDeathGrip]() { + EnableDragDrop(aEnable); + })); +} + void nsBaseWidget::RegisterPluginWindowForRemoteUpdates() { diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index bbc6b72383..ab29fcd0ff 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -243,6 +243,7 @@ public: NS_IMETHOD SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override; virtual LayoutDeviceIntPoint GetClientOffset() override; virtual void EnableDragDrop(bool aEnable) override {}; + virtual nsresult AsyncEnableDragDrop(bool aEnable) override; NS_IMETHOD GetAttention(int32_t aCycleCount) override; virtual bool HasPendingInputEvent() override; NS_IMETHOD SetIcon(const nsAString &anIconSpec) override; diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index 8e28c24da5..fe21b67275 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -1378,6 +1378,7 @@ class nsIWidget : public nsISupports * Enables the dropping of files to a widget. */ virtual void EnableDragDrop(bool aEnable) = 0; + virtual nsresult AsyncEnableDragDrop(bool aEnable) = 0; /** * Enables/Disables system mouse capture. diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 8f614d8628..295518ea26 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -3715,22 +3715,21 @@ nsWindow::ClientToWindowSize(const LayoutDeviceIntSize& aClientSize) void nsWindow::EnableDragDrop(bool aEnable) { - NS_ASSERTION(mWnd, "nsWindow::EnableDragDrop() called after Destroy()"); + if (!mWnd) { + // Return early if the window already closed + return; + } nsresult rv = NS_ERROR_FAILURE; if (aEnable) { if (!mNativeDragTarget) { mNativeDragTarget = new nsNativeDragTarget(this); mNativeDragTarget->AddRef(); - if (SUCCEEDED(::CoLockObjectExternal((LPUNKNOWN)mNativeDragTarget, - TRUE, FALSE))) { - ::RegisterDragDrop(mWnd, (LPDROPTARGET)mNativeDragTarget); - } + ::RegisterDragDrop(mWnd, (LPDROPTARGET)mNativeDragTarget); } } else { if (mWnd && mNativeDragTarget) { ::RevokeDragDrop(mWnd); - ::CoLockObjectExternal((LPUNKNOWN)mNativeDragTarget, FALSE, TRUE); mNativeDragTarget->DragCancel(); NS_RELEASE(mNativeDragTarget); } diff --git a/xpcom/io/nsLocalFileWin.cpp b/xpcom/io/nsLocalFileWin.cpp index e5a0131a77..a86d468775 100644 --- a/xpcom/io/nsLocalFileWin.cpp +++ b/xpcom/io/nsLocalFileWin.cpp @@ -3016,6 +3016,8 @@ nsLocalFile::IsExecutable(bool* aResult) "air", // Adobe AIR installer "app", // executable application "application", // from bug 348763 + "appx", + "appxbundle", "asp", "bas", "bat", @@ -3058,6 +3060,8 @@ nsLocalFile::IsExecutable(bool* aResult) "msh", // Microsoft Shell "mshxml", // Microsoft Shell "msi", + "msix", + "msixbundle", "msp", "mst", "ops", // Office Profile Settings |