Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2023-10-26 10:55:31 +08:00
commit bac9ec9a84
39 changed files with 541 additions and 108 deletions

View file

@ -115,6 +115,27 @@ Crypto::GetRandomValues(JSContext* aCx, const ArrayBufferView& aArray,
aRetval.set(view); aRetval.set(view);
} }
void Crypto::RandomUUID(nsAString& aRetVal)
{
// NSID_LENGTH == 39 == 36 UUID chars + 2 curly braces + 1 NUL byte
static_assert(NSID_LENGTH == 39);
nsCOMPtr<nsIUUIDGenerator> uuidgen =
do_GetService("@mozilla.org/uuid-generator;1");
nsID uuid;
nsresult rv = uuidgen->GenerateUUIDInPlace(&uuid);
char uuidBuffer[NSID_LENGTH];
uuid.ToProvidedString(uuidBuffer);
nsCString asciiString(uuidBuffer);
// Convert UUID chars to UTF-16 retval, omitting the curly braces and NUL
CopyASCIItoUTF16(Substring(asciiString, 1, NSID_LENGTH - 3), aRetVal);
}
SubtleCrypto* SubtleCrypto*
Crypto::Subtle() Crypto::Subtle()
{ {

View file

@ -9,6 +9,7 @@
#include "mozilla/dom/SubtleCrypto.h" #include "mozilla/dom/SubtleCrypto.h"
#include "nsIGlobalObject.h" #include "nsIGlobalObject.h"
#include "nsString.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"
#include "mozilla/dom/TypedArray.h" #include "mozilla/dom/TypedArray.h"
#define NS_DOMCRYPTO_CID \ #define NS_DOMCRYPTO_CID \
@ -39,6 +40,8 @@ public:
JS::MutableHandle<JSObject*> aRetval, JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv); ErrorResult& aRv);
void RandomUUID(nsAString& aRetVal);
SubtleCrypto* SubtleCrypto*
Subtle(); Subtle();

View file

@ -190,7 +190,7 @@ TypeUtils::ToCacheResponseWithoutBody(CacheResponse& aOut,
aOut.statusText() = aIn.GetUnfilteredStatusText(); aOut.statusText() = aIn.GetUnfilteredStatusText();
RefPtr<InternalHeaders> headers = aIn.UnfilteredHeaders(); RefPtr<InternalHeaders> headers = aIn.UnfilteredHeaders();
MOZ_DIAGNOSTIC_ASSERT(headers); MOZ_DIAGNOSTIC_ASSERT(headers);
if (HasVaryStar(headers)) { if (aIn.Type() != ResponseType::Opaque && HasVaryStar(headers)) {
aRv.ThrowTypeError<MSG_RESPONSE_HAS_VARY_STAR>(); aRv.ThrowTypeError<MSG_RESPONSE_HAS_VARY_STAR>();
return; return;
} }

View file

@ -8,6 +8,7 @@
#include <stdarg.h> #include <stdarg.h>
#include "gfxPrefs.h"
#include "GLContextTypes.h" #include "GLContextTypes.h"
#include "GLDefs.h" #include "GLDefs.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
@ -1397,6 +1398,7 @@ protected:
CheckedUint32 mGeneration; CheckedUint32 mGeneration;
WebGLContextOptions mOptions; WebGLContextOptions mOptions;
const uint32_t mMaxVertIdsPerDraw = gfxPrefs::WebglMaxVertIDsPerDraw();
bool mInvalidated; bool mInvalidated;
bool mCapturedFrameInvalidated; bool mCapturedFrameInvalidated;

View file

@ -608,6 +608,12 @@ WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertCount,
MakeContextCurrent(); 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; bool error = false;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error); ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error) if (error)
@ -850,6 +856,12 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei vertCount, GLenum type,
MakeContextCurrent(); 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; bool error = false;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error); ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error) if (error)

View file

@ -7,6 +7,8 @@
#include "MediaInfo.h" #include "MediaInfo.h"
#include "VideoUtils.h" #include "VideoUtils.h"
#include "ImageContainer.h" #include "ImageContainer.h"
#include "mozilla/layers/SharedRGBImage.h"
#include "YCbCrUtils.h"
#include <stdint.h> #include <stdint.h>
@ -89,6 +91,45 @@ ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane)
aPlane.mStride > 0 && aPlane.mWidth <= aPlane.mStride; 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, VideoData::VideoData(int64_t aOffset,
int64_t aTime, int64_t aTime,
int64_t aDuration, int64_t aDuration,
@ -242,36 +283,7 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
return v.forget(); return v.forget();
} }
// The following situation should never happen unless there is a bug if (!ValidateBufferAndPicture(aBuffer, aPicture)) {
// 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");
return nullptr; return nullptr;
} }
@ -305,6 +317,73 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
return v.forget(); return v.forget();
} }
/* 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 */ /* static */
already_AddRefed<VideoData> already_AddRefed<VideoData>
VideoData::CreateFromImage(const VideoInfo& aInfo, VideoData::CreateFromImage(const VideoInfo& aInfo,
@ -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> already_AddRefed<MediaRawData>
MediaRawData::Clone() const MediaRawData::Clone() const
{ {
@ -356,6 +444,9 @@ MediaRawData::Clone() const
if (!s->mBuffer.Append(mBuffer.Data(), mBuffer.Length())) { if (!s->mBuffer.Append(mBuffer.Data(), mBuffer.Length())) {
return nullptr; return nullptr;
} }
if (!s->mAlphaBuffer.Append(mAlphaBuffer.Data(), mAlphaBuffer.Length())) {
return nullptr;
}
return s.forget(); return s.forget();
} }

View file

@ -474,6 +474,17 @@ public:
int64_t aTimecode, int64_t aTimecode,
const IntRect& aPicture); 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, static already_AddRefed<VideoData> CreateAndCopyIntoTextureClient(const VideoInfo& aInfo,
int64_t aOffset, int64_t aOffset,
int64_t aTime, int64_t aTime,
@ -622,15 +633,22 @@ private:
class MediaRawData : public MediaData { class MediaRawData : public MediaData {
public: public:
MediaRawData(); 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 // Pointer to data or null if not-yet allocated
const uint8_t* Data() const { return mBuffer.Data(); } 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 of buffer.
size_t Size() const { return mBuffer.Length(); } size_t Size() const { return mBuffer.Length(); }
size_t AlphaSize() const { return mAlphaBuffer.Length(); }
size_t ComputedSizeOfIncludingThis() const size_t ComputedSizeOfIncludingThis() const
{ {
return sizeof(*this) + mBuffer.ComputedSizeOfExcludingThis(); return sizeof(*this)
+ mBuffer.ComputedSizeOfExcludingThis()
+ mAlphaBuffer.ComputedSizeOfExcludingThis();
} }
// Access the buffer as a Span. // Access the buffer as a Span.
operator Span<const uint8_t>() { return MakeSpan(Data(), Size()); } operator Span<const uint8_t>() { return MakeSpan(Data(), Size()); }
@ -661,6 +679,7 @@ protected:
private: private:
friend class MediaRawDataWriter; friend class MediaRawDataWriter;
AlignedByteBuffer mBuffer; AlignedByteBuffer mBuffer;
AlignedByteBuffer mAlphaBuffer;
CryptoSample mCryptoInternal; CryptoSample mCryptoInternal;
MediaRawData(const MediaRawData&); // Not implemented MediaRawData(const MediaRawData&); // Not implemented
}; };

View file

@ -215,6 +215,7 @@ public:
, mRotation(aOther.mRotation) , mRotation(aOther.mRotation)
, mBitDepth(aOther.mBitDepth) , mBitDepth(aOther.mBitDepth)
, mImageRect(aOther.mImageRect) , mImageRect(aOther.mImageRect)
, mAlphaPresent(aOther.mAlphaPresent)
{ {
} }
@ -238,6 +239,16 @@ public:
return MakeUnique<VideoInfo>(*this); return MakeUnique<VideoInfo>(*this);
} }
void SetAlpha(bool aAlphaPresent)
{
mAlphaPresent = aAlphaPresent;
}
bool HasAlpha() const
{
return mAlphaPresent;
}
nsIntRect ImageRect() const nsIntRect ImageRect() const
{ {
if (mImageRect.width < 0 || mImageRect.height < 0) { if (mImageRect.width < 0 || mImageRect.height < 0) {
@ -312,6 +323,9 @@ private:
// mImage may be cropped; currently only used with the WebM container. // mImage may be cropped; currently only used with the WebM container.
// A negative width or height indicate that no cropping is to occur. // A negative width or height indicate that no cropping is to occur.
nsIntRect mImageRect; nsIntRect mImageRect;
// Indicates whether or not frames may contain alpha information.
bool mAlphaPresent = false;
}; };
class AudioInfo : public TrackInfo { class AudioInfo : public TrackInfo {

View file

@ -62,7 +62,7 @@ MediaSourceDemuxer::AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes
RefPtr<MediaSourceDecoder::ResourceSizes> sizes = aSizes; RefPtr<MediaSourceDecoder::ResourceSizes> sizes = aSizes;
nsCOMPtr<nsIRunnable> task = nsCOMPtr<nsIRunnable> task =
NS_NewRunnableFunction([self, sizes] () { NS_NewRunnableFunction([self, sizes] () {
for (TrackBuffersManager* manager : self->mSourceBuffers) { for (const RefPtr<TrackBuffersManager>& manager : self->mSourceBuffers) {
manager->AddSizeOfResources(sizes); manager->AddSizeOfResources(sizes);
} }
}); });
@ -171,42 +171,45 @@ MediaSourceDemuxer::GetCrypto()
} }
void void
MediaSourceDemuxer::AttachSourceBuffer(TrackBuffersManager* aSourceBuffer) MediaSourceDemuxer::AttachSourceBuffer(
RefPtr<TrackBuffersManager>& aSourceBuffer)
{ {
nsCOMPtr<nsIRunnable> task = nsCOMPtr<nsIRunnable> task = NewRunnableMethod<RefPtr<TrackBuffersManager>&&>(
NewRunnableMethod<TrackBuffersManager*>(
this, &MediaSourceDemuxer::DoAttachSourceBuffer, this, &MediaSourceDemuxer::DoAttachSourceBuffer,
aSourceBuffer); aSourceBuffer);
GetTaskQueue()->Dispatch(task.forget()); GetTaskQueue()->Dispatch(task.forget());
} }
void void
MediaSourceDemuxer::DoAttachSourceBuffer(mozilla::TrackBuffersManager* aSourceBuffer) MediaSourceDemuxer::DoAttachSourceBuffer(
RefPtr<mozilla::TrackBuffersManager>&& aSourceBuffer)
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
mSourceBuffers.AppendElement(aSourceBuffer); mSourceBuffers.AppendElement(Move(aSourceBuffer));
ScanSourceBuffersForContent(); ScanSourceBuffersForContent();
} }
void void
MediaSourceDemuxer::DetachSourceBuffer(TrackBuffersManager* aSourceBuffer) MediaSourceDemuxer::DetachSourceBuffer(
RefPtr<TrackBuffersManager>& aSourceBuffer)
{ {
nsCOMPtr<nsIRunnable> task = RefPtr<MediaSourceDemuxer> self = this;
NewRunnableMethod<TrackBuffersManager*>( nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
this, &MediaSourceDemuxer::DoDetachSourceBuffer, [self, aSourceBuffer]() {
aSourceBuffer); self->DoDetachSourceBuffer(aSourceBuffer);
});
GetTaskQueue()->Dispatch(task.forget()); GetTaskQueue()->Dispatch(task.forget());
} }
void void
MediaSourceDemuxer::DoDetachSourceBuffer(TrackBuffersManager* aSourceBuffer) MediaSourceDemuxer::DoDetachSourceBuffer(
const RefPtr<TrackBuffersManager>& aSourceBuffer)
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
for (uint32_t i = 0; i < mSourceBuffers.Length(); i++) { mSourceBuffers.RemoveElementsBy(
if (mSourceBuffers[i].get() == aSourceBuffer) { [&aSourceBuffer](const RefPtr<TrackBuffersManager> aLinkedSourceBuffer) {
mSourceBuffers.RemoveElementAt(i); return aLinkedSourceBuffer == aSourceBuffer;
} });
}
if (aSourceBuffer == mAudioTrack) { if (aSourceBuffer == mAudioTrack) {
mAudioTrack = nullptr; mAudioTrack = nullptr;
} }
@ -230,7 +233,7 @@ MediaSourceDemuxer::GetTrackInfo(TrackType aTrack)
} }
} }
TrackBuffersManager* RefPtr<TrackBuffersManager>
MediaSourceDemuxer::GetManager(TrackType aTrack) MediaSourceDemuxer::GetManager(TrackType aTrack)
{ {
MonitorAutoLock mon(mMonitor); MonitorAutoLock mon(mMonitor);

View file

@ -45,8 +45,8 @@ public:
void NotifyDataArrived() override; void NotifyDataArrived() override;
/* interface for TrackBuffersManager */ /* interface for TrackBuffersManager */
void AttachSourceBuffer(TrackBuffersManager* aSourceBuffer); void AttachSourceBuffer(RefPtr<TrackBuffersManager>& aSourceBuffer);
void DetachSourceBuffer(TrackBuffersManager* aSourceBuffer); void DetachSourceBuffer(RefPtr<TrackBuffersManager>& aSourceBuffer);
AutoTaskQueue* GetTaskQueue() { return mTaskQueue; } AutoTaskQueue* GetTaskQueue() { return mTaskQueue; }
// Returns a string describing the state of the MediaSource internal // Returns a string describing the state of the MediaSource internal
@ -64,10 +64,10 @@ private:
// Scan source buffers and update information. // Scan source buffers and update information.
bool ScanSourceBuffersForContent(); bool ScanSourceBuffersForContent();
RefPtr<InitPromise> AttemptInit(); RefPtr<InitPromise> AttemptInit();
TrackBuffersManager* GetManager(TrackInfo::TrackType aType); RefPtr<TrackBuffersManager> GetManager(TrackInfo::TrackType aType);
TrackInfo* GetTrackInfo(TrackInfo::TrackType); TrackInfo* GetTrackInfo(TrackInfo::TrackType);
void DoAttachSourceBuffer(TrackBuffersManager* aSourceBuffer); void DoAttachSourceBuffer(RefPtr<TrackBuffersManager>&& aSourceBuffer);
void DoDetachSourceBuffer(TrackBuffersManager* aSourceBuffer); void DoDetachSourceBuffer(const RefPtr<TrackBuffersManager>& aSourceBuffer);
bool OnTaskQueue() bool OnTaskQueue()
{ {
return !GetTaskQueue() || GetTaskQueue()->IsCurrentThreadIn(); return !GetTaskQueue() || GetTaskQueue()->IsCurrentThreadIn();

View file

@ -281,7 +281,7 @@ SourceBuffer::Detach()
if (mTrackBuffersManager) { if (mTrackBuffersManager) {
mTrackBuffersManager->Detach(); mTrackBuffersManager->Detach();
mMediaSource->GetDecoder()->GetDemuxer()->DetachSourceBuffer( mMediaSource->GetDecoder()->GetDemuxer()->DetachSourceBuffer(
mTrackBuffersManager.get()); mTrackBuffersManager);
} }
mTrackBuffersManager = nullptr; mTrackBuffersManager = nullptr;
mMediaSource = nullptr; mMediaSource = nullptr;
@ -321,7 +321,7 @@ SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
SetMode(SourceBufferAppendMode::Segments, dummy); SetMode(SourceBufferAppendMode::Segments, dummy);
} }
mMediaSource->GetDecoder()->GetDemuxer()->AttachSourceBuffer( mMediaSource->GetDecoder()->GetDemuxer()->AttachSourceBuffer(
mTrackBuffersManager.get()); mTrackBuffersManager);
} }
SourceBuffer::~SourceBuffer() SourceBuffer::~SourceBuffer()

View file

@ -35,6 +35,38 @@ static VPXDecoder::Codec MimeTypeToCodec(const nsACString& aMimeType)
return VPXDecoder::Codec::Unknown; 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) VPXDecoder::VPXDecoder(const CreateDecoderParams& aParams)
: mImageContainer(aParams.mImageContainer) : mImageContainer(aParams.mImageContainer)
, mTaskQueue(aParams.mTaskQueue) , mTaskQueue(aParams.mTaskQueue)
@ -45,6 +77,7 @@ VPXDecoder::VPXDecoder(const CreateDecoderParams& aParams)
{ {
MOZ_COUNT_CTOR(VPXDecoder); MOZ_COUNT_CTOR(VPXDecoder);
PodZero(&mVPX); PodZero(&mVPX);
PodZero(&mVPXAlpha);
} }
VPXDecoder::~VPXDecoder() VPXDecoder::~VPXDecoder()
@ -56,34 +89,24 @@ void
VPXDecoder::Shutdown() VPXDecoder::Shutdown()
{ {
vpx_codec_destroy(&mVPX); vpx_codec_destroy(&mVPX);
vpx_codec_destroy(&mVPXAlpha);
} }
RefPtr<MediaDataDecoder::InitPromise> RefPtr<MediaDataDecoder::InitPromise>
VPXDecoder::Init() VPXDecoder::Init()
{ {
int decode_threads = 2; if (NS_FAILED(InitContext(&mVPX, mInfo, mCodec))) {
return VPXDecoder::InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR,
vpx_codec_iface_t* dx = nullptr; __func__);
if (mCodec == Codec::VP8) { }
dx = vpx_codec_vp8_dx(); if (mInfo.HasAlpha()) {
} else if (mCodec == Codec::VP9) { if (NS_FAILED(InitContext(&mVPXAlpha, mInfo, mCodec))) {
dx = vpx_codec_vp9_dx(); return VPXDecoder::InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR,
if (mInfo.mDisplay.width >= 2048) { __func__);
decode_threads = 8;
} else if (mInfo.mDisplay.width >= 1024) {
decode_threads = 4;
} }
} }
decode_threads = std::min(decode_threads, PR_GetNumberOfProcessors()); return VPXDecoder::InitPromise::CreateAndResolve(TrackInfo::kVideoTrack,
__func__);
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__);
}
return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__);
} }
void void
@ -117,12 +140,25 @@ VPXDecoder::DoDecode(MediaRawData* aSample)
vpx_codec_iter_t iter = nullptr; vpx_codec_iter_t iter = nullptr;
vpx_image_t *img; vpx_image_t *img;
vpx_image_t *img_alpha = nullptr;
bool alpha_decoded = false;
while ((img = vpx_codec_get_frame(&mVPX, &iter))) { while ((img = vpx_codec_get_frame(&mVPX, &iter))) {
NS_ASSERTION(img->fmt == VPX_IMG_FMT_I420 || NS_ASSERTION(img->fmt == VPX_IMG_FMT_I420 ||
img->fmt == VPX_IMG_FMT_I444, img->fmt == VPX_IMG_FMT_I444,
"WebM image format not I420 or 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 // Chroma shifts are rounded down as per the decoding examples in the SDK
VideoData::YCbCrBuffer b; VideoData::YCbCrBuffer b;
b.mPlanes[0].mData = img->planes[0]; b.mPlanes[0].mData = img->planes[0];
@ -174,8 +210,9 @@ VPXDecoder::DoDecode(MediaRawData* aSample)
}(); }();
// TODO: need a newer libvpx to support full color range // TODO: need a newer libvpx to support full color range
RefPtr<VideoData> v = RefPtr<VideoData> v;
VideoData::CreateAndCopyData(mInfo, if (!img_alpha) {
v = VideoData::CreateAndCopyData(mInfo,
mImageContainer, mImageContainer,
aSample->mOffset, aSample->mOffset,
aSample->mTime, aSample->mTime,
@ -185,6 +222,26 @@ VPXDecoder::DoDecode(MediaRawData* aSample)
aSample->mTimecode, aSample->mTimecode,
mInfo.ScaledImageRect(img->d_w, mInfo.ScaledImageRect(img->d_w,
img->d_h)); 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) { if (!v) {
LOG("Image allocation error source %ldx%ld display %ldx%ld picture %ldx%ld", 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)); 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 */ /* static */
bool bool
VPXDecoder::IsVPX(const nsACString& aMimeType, uint8_t aCodecMask) VPXDecoder::IsVPX(const nsACString& aMimeType, uint8_t aCodecMask)

View file

@ -57,6 +57,8 @@ private:
void ProcessDecode(MediaRawData* aSample); void ProcessDecode(MediaRawData* aSample);
MediaResult DoDecode(MediaRawData* aSample); MediaResult DoDecode(MediaRawData* aSample);
void ProcessDrain(); void ProcessDrain();
MediaResult DecodeAlpha(vpx_image_t** aImgAlpha,
MediaRawData* aSample);
const RefPtr<ImageContainer> mImageContainer; const RefPtr<ImageContainer> mImageContainer;
const RefPtr<TaskQueue> mTaskQueue; const RefPtr<TaskQueue> mTaskQueue;
@ -66,6 +68,9 @@ private:
// VPx decoder state // VPx decoder state
vpx_codec_ctx_t mVPX; vpx_codec_ctx_t mVPX;
// VPx alpha decoder state
vpx_codec_ctx_t mVPXAlpha;
const VideoInfo& mInfo; const VideoInfo& mInfo;
const Codec mCodec; const Codec mCodec;

View file

@ -32,6 +32,13 @@ public:
already_AddRefed<MediaDataDecoder> already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const CreateDecoderParams& aParams) override 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 = RefPtr<MediaDataDecoder> decoder =
new FFmpegVideoDecoder<V>(mLib, new FFmpegVideoDecoder<V>(mLib,
aParams.mTaskQueue, aParams.mTaskQueue,

View file

@ -83,6 +83,14 @@ WMFDecoderModule::Startup()
already_AddRefed<MediaDataDecoder> already_AddRefed<MediaDataDecoder>
WMFDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams) 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( nsAutoPtr<WMFVideoMFTManager> manager(
new WMFVideoMFTManager(aParams.VideoConfig(), new WMFVideoMFTManager(aParams.VideoConfig(),
aParams.mKnowsCompositor, aParams.mKnowsCompositor,

View file

@ -378,6 +378,7 @@ WebMDemuxer::ReadMetadata()
mInfo.mVideo.mDisplay = displaySize; mInfo.mVideo.mDisplay = displaySize;
mInfo.mVideo.mImage = frameSize; mInfo.mVideo.mImage = frameSize;
mInfo.mVideo.SetImageRect(pictureRect); mInfo.mVideo.SetImageRect(pictureRect);
mInfo.mVideo.SetAlpha(params.alpha_mode);
switch (params.stereo_mode) { switch (params.stereo_mode) {
case NESTEGG_VIDEO_MONO: case NESTEGG_VIDEO_MONO:
@ -656,6 +657,21 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
WEBM_DEBUG("nestegg_packet_data failed r=%d", r); WEBM_DEBUG("nestegg_packet_data failed r=%d", r);
return NS_ERROR_DOM_MEDIA_DEMUXER_ERR; 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; bool isKeyframe = false;
if (aType == TrackInfo::kAudioTrack) { if (aType == TrackInfo::kAudioTrack) {
isKeyframe = true; isKeyframe = true;
@ -713,11 +729,20 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
WEBM_DEBUG("push sample tstamp: %ld next_tstamp: %ld length: %ld kf: %d", WEBM_DEBUG("push sample tstamp: %ld next_tstamp: %ld length: %ld kf: %d",
tstamp, next_tstamp, length, isKeyframe); tstamp, next_tstamp, length, isKeyframe);
RefPtr<MediaRawData> sample = new MediaRawData(data, length); 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()) { if (length && !sample->Data()) {
// OOM. // OOM.
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
}
sample->mTimecode = tstamp; sample->mTimecode = tstamp;
sample->mTime = tstamp; sample->mTime = tstamp;
sample->mDuration = next_tstamp - tstamp; sample->mDuration = next_tstamp - tstamp;

View file

@ -18,4 +18,7 @@ interface Crypto {
[Throws] [Throws]
ArrayBufferView getRandomValues(ArrayBufferView array); ArrayBufferView getRandomValues(ArrayBufferView array);
[SecureContext]
DOMString randomUUID();
}; };

View file

@ -241,6 +241,7 @@ private:
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{ {
nsresult rv = mWrappedRunnable->Run(); nsresult rv = mWrappedRunnable->Run();
mWrappedRunnable = nullptr;
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
if (!JS_IsExceptionPending(aCx)) { if (!JS_IsExceptionPending(aCx)) {
Throw(aCx, rv); Throw(aCx, rv);
@ -259,6 +260,7 @@ private:
MOZ_ASSERT(cancelable); // We checked this earlier! MOZ_ASSERT(cancelable); // We checked this earlier!
rv = cancelable->Cancel(); rv = cancelable->Cancel();
nsresult rv2 = WorkerRunnable::Cancel(); nsresult rv2 = WorkerRunnable::Cancel();
mWrappedRunnable = nullptr;
return NS_FAILED(rv) ? rv : rv2; return NS_FAILED(rv) ? rv : rv2;
} }
}; };

View file

@ -106,8 +106,33 @@ SharedRGBImage::GetTextureClient(KnowsCompositor* aForwarder)
already_AddRefed<gfx::SourceSurface> already_AddRefed<gfx::SourceSurface>
SharedRGBImage::GetAsSourceSurface() SharedRGBImage::GetAsSourceSurface()
{ {
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; return nullptr;
} }
surface = drawTarget->Snapshot();
}
mSourceSurface = surface;
return surface.forget();
}
} // namespace layers } // namespace layers
} // namespace mozilla } // namespace mozilla

View file

@ -51,6 +51,7 @@ private:
gfx::IntSize mSize; gfx::IntSize mSize;
RefPtr<ImageClient> mCompositable; RefPtr<ImageClient> mCompositable;
RefPtr<TextureClient> mTextureClient; RefPtr<TextureClient> mTextureClient;
nsCountedRef<nsMainThreadSourceSurfaceRef> mSourceSurface;
}; };
} // namespace layers } // namespace layers

View file

@ -601,6 +601,7 @@ private:
DECL_GFX_PREF(Live, "webgl.lose-context-on-memory-pressure", WebGLLoseContextOnMemoryPressure, 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-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.min_capability_mode", WebGLMinCapabilityMode, bool, false);
DECL_GFX_PREF(Live, "webgl.msaa-force", WebGLForceMSAA, bool, false); DECL_GFX_PREF(Live, "webgl.msaa-force", WebGLForceMSAA, bool, false);
DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false); DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false);

View file

@ -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 gfx
} // namespace mozilla } // namespace mozilla

View file

@ -24,6 +24,17 @@ ConvertYCbCrToRGB(const layers::PlanarYCbCrData& aData,
unsigned char* aDestBuffer, unsigned char* aDestBuffer,
int32_t aStride); 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 gfx
} // namespace mozilla } // namespace mozilla

View file

@ -550,6 +550,27 @@ void ScaleYCbCrToRGB32_deprecated(const uint8_t* y_buf,
if (has_mmx) if (has_mmx)
EMMS(); 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 gfx
} // namespace mozilla } // namespace mozilla

View file

@ -106,6 +106,18 @@ void ScaleYCbCrToRGB32_deprecated(const uint8_t* yplane,
Rotate view_rotate, Rotate view_rotate,
ScaleFilter filter); 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 gfx
} // namespace mozilla } // namespace mozilla

View file

@ -9,6 +9,7 @@ nestegg_duration
nestegg_free_packet nestegg_free_packet
nestegg_init nestegg_init
nestegg_offset_seek nestegg_offset_seek
nestegg_packet_additional_data
nestegg_packet_count nestegg_packet_count
nestegg_packet_discard_padding nestegg_packet_discard_padding
nestegg_packet_data nestegg_packet_data

View file

@ -32,6 +32,7 @@ random == poster-12.html poster-ref-blue140x100.html
== poster-13.html poster-ref-blue400x300.html == poster-13.html poster-ref-blue400x300.html
== poster-15.html poster-ref-green70x30.html == poster-15.html poster-ref-green70x30.html
random-if(winWidget) random-if(cocoaWidget) == bug686957.html bug686957-ref.html # bug 922951 for OS X 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': # Tests for <video src> with 'object-fit' & 'object-position':
# These tests should be very similar to tests in our w3c-css/submitted/images3 # These tests should be very similar to tests in our w3c-css/submitted/images3

View file

@ -0,0 +1,5 @@
<!DOCTYPE HTML>
<html>
<body style="background:black;">
</body>
</html>

View file

@ -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>

Binary file not shown.

View file

@ -513,10 +513,16 @@ WebrtcGmpVideoEncoder::Terminated()
{ {
LOGD(("GMP Encoder Terminated: %p", (void *)this)); LOGD(("GMP Encoder Terminated: %p", (void *)this));
mGMP->Close(); GMPVideoEncoderProxy* gmp(mGMP);
mGMP = nullptr; mGMP = nullptr;
mHost = nullptr; mHost = nullptr;
mInitting = false; mInitting = false;
if (gmp) {
// Do this last, since this could cause us to be destroyed
gmp->Close();
}
// Could now notify that it's dead // Could now notify that it's dead
} }

View file

@ -4320,6 +4320,7 @@ pref("webgl.can-lose-context-in-foreground", true);
pref("webgl.restore-context-when-visible", true); pref("webgl.restore-context-when-visible", true);
pref("webgl.max-warnings-per-context", 32); pref("webgl.max-warnings-per-context", 32);
pref("webgl.max-size-per-texture-mb", 1024); 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-draft-extensions", false);
pref("webgl.enable-privileged-extensions", false); pref("webgl.enable-privileged-extensions", false);
pref("webgl.bypass-shader-validation", false); pref("webgl.bypass-shader-validation", false);

View file

@ -3329,7 +3329,8 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
0x1F, /* 0x20, */ 0x00 }; 0x1F, /* 0x20, */ 0x3B, 0x3D, 0x7F,
0x00 };
if (cookieAttributes.name.FindCharInSet(illegalNameCharacters, 0) != -1) { if (cookieAttributes.name.FindCharInSet(illegalNameCharacters, 0) != -1) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader, "invalid name character"); COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader, "invalid name character");
return newCookie; return newCookie;

View file

@ -695,7 +695,10 @@ nsresult nsView::AttachToTopLevelWidget(nsIWidget* aWidget)
mWindow = aWidget; mWindow = aWidget;
mWindow->SetAttachedWidgetListener(this); mWindow->SetAttachedWidgetListener(this);
mWindow->EnableDragDrop(true); if (mWindow->WindowType() != eWindowType_invisible) {
nsresult rv = mWindow->AsyncEnableDragDrop(true);
NS_ENSURE_SUCCESS(rv, rv);
}
mWidgetIsTopLevel = true; mWidgetIsTopLevel = true;
// Refresh the view bounds // Refresh the view bounds

View file

@ -2133,6 +2133,16 @@ nsBaseWidget::UpdateSynthesizedTouchState(MultiTouchInput* aState,
return inputToDispatch; return inputToDispatch;
} }
nsresult
nsBaseWidget::AsyncEnableDragDrop(bool aEnable)
{
RefPtr<nsBaseWidget> kungFuDeathGrip = this;
return NS_IdleDispatchToCurrentThread(
NS_NewRunnableFunction([this, aEnable, kungFuDeathGrip]() {
EnableDragDrop(aEnable);
}));
}
void void
nsBaseWidget::RegisterPluginWindowForRemoteUpdates() nsBaseWidget::RegisterPluginWindowForRemoteUpdates()
{ {

View file

@ -243,6 +243,7 @@ public:
NS_IMETHOD SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override; NS_IMETHOD SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override;
virtual LayoutDeviceIntPoint GetClientOffset() override; virtual LayoutDeviceIntPoint GetClientOffset() override;
virtual void EnableDragDrop(bool aEnable) override {}; virtual void EnableDragDrop(bool aEnable) override {};
virtual nsresult AsyncEnableDragDrop(bool aEnable) override;
NS_IMETHOD GetAttention(int32_t aCycleCount) override; NS_IMETHOD GetAttention(int32_t aCycleCount) override;
virtual bool HasPendingInputEvent() override; virtual bool HasPendingInputEvent() override;
NS_IMETHOD SetIcon(const nsAString &anIconSpec) override; NS_IMETHOD SetIcon(const nsAString &anIconSpec) override;

View file

@ -1378,6 +1378,7 @@ class nsIWidget : public nsISupports
* Enables the dropping of files to a widget. * Enables the dropping of files to a widget.
*/ */
virtual void EnableDragDrop(bool aEnable) = 0; virtual void EnableDragDrop(bool aEnable) = 0;
virtual nsresult AsyncEnableDragDrop(bool aEnable) = 0;
/** /**
* Enables/Disables system mouse capture. * Enables/Disables system mouse capture.

View file

@ -3734,22 +3734,21 @@ nsWindow::ClientToWindowSize(const LayoutDeviceIntSize& aClientSize)
void void
nsWindow::EnableDragDrop(bool aEnable) 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; nsresult rv = NS_ERROR_FAILURE;
if (aEnable) { if (aEnable) {
if (!mNativeDragTarget) { if (!mNativeDragTarget) {
mNativeDragTarget = new nsNativeDragTarget(this); mNativeDragTarget = new nsNativeDragTarget(this);
mNativeDragTarget->AddRef(); mNativeDragTarget->AddRef();
if (SUCCEEDED(::CoLockObjectExternal((LPUNKNOWN)mNativeDragTarget,
TRUE, FALSE))) {
::RegisterDragDrop(mWnd, (LPDROPTARGET)mNativeDragTarget); ::RegisterDragDrop(mWnd, (LPDROPTARGET)mNativeDragTarget);
} }
}
} else { } else {
if (mWnd && mNativeDragTarget) { if (mWnd && mNativeDragTarget) {
::RevokeDragDrop(mWnd); ::RevokeDragDrop(mWnd);
::CoLockObjectExternal((LPUNKNOWN)mNativeDragTarget, FALSE, TRUE);
mNativeDragTarget->DragCancel(); mNativeDragTarget->DragCancel();
NS_RELEASE(mNativeDragTarget); NS_RELEASE(mNativeDragTarget);
} }

View file

@ -3020,6 +3020,8 @@ nsLocalFile::IsExecutable(bool* aResult)
"air", // Adobe AIR installer "air", // Adobe AIR installer
"app", // executable application "app", // executable application
"application", // from bug 348763 "application", // from bug 348763
"appx",
"appxbundle",
"asp", "asp",
"bas", "bas",
"bat", "bat",
@ -3062,6 +3064,8 @@ nsLocalFile::IsExecutable(bool* aResult)
"msh", // Microsoft Shell "msh", // Microsoft Shell
"mshxml", // Microsoft Shell "mshxml", // Microsoft Shell
"msi", "msi",
"msix",
"msixbundle",
"msp", "msp",
"mst", "mst",
"ops", // Office Profile Settings "ops", // Office Profile Settings