Bug 1336510 - Part 4: Capture a strong reference to this in dom/media, r=jwwang

MozReview-Commit-ID: 4lVGrGzhVXh
This commit is contained in:
Michael Layzell 2017-02-03 16:57:49 -05:00
Родитель f225a42d33
Коммит 1d0870e2e1
8 изменённых файлов: 87 добавлений и 67 удалений

Просмотреть файл

@ -1813,13 +1813,14 @@ MediaDecoder::DumpDebugInfo()
return;
}
RefPtr<MediaDecoder> self = this;
GetStateMachine()->RequestDebugInfo()->Then(
AbstractThread::MainThread(), __func__,
[this, str] (const nsACString& aString) {
[this, self, str] (const nsACString& aString) {
DUMP_LOG("%s", str.get());
DUMP_LOG("%s", aString.Data());
},
[this, str] () {
[this, self, str] () {
DUMP_LOG("%s", str.get());
});
}

Просмотреть файл

@ -2821,9 +2821,10 @@ nsresult MediaDecoderStateMachine::Init(MediaDecoder* aDecoder)
mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
RefPtr<MediaDecoderStateMachine> self = this;
mOnMediaNotSeekable = mReader->OnMediaNotSeekable().Connect(
OwnerThread(), [this] () {
mMediaSeekable = false;
OwnerThread(), [self] () {
self->mMediaSeekable = false;
});
mMediaSink = CreateMediaSink(mAudioCaptured);
@ -2837,7 +2838,6 @@ nsresult MediaDecoderStateMachine::Init(MediaDecoder* aDecoder)
nsresult rv = mReader->Init();
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<MediaDecoderStateMachine> self = this;
OwnerThread()->Dispatch(NS_NewRunnableFunction([self] () {
MOZ_ASSERT(!self->mStateObj);
auto s = new DecodeMetadataState(self);
@ -3112,9 +3112,10 @@ MediaDecoderStateMachine::RequestAudioData()
SAMPLE_LOG("Queueing audio task - queued=%" PRIuSIZE ", decoder-queued=%" PRIuSIZE,
AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
RefPtr<MediaDecoderStateMachine> self = this;
mReader->RequestAudioData()->Then(
OwnerThread(), __func__,
[this] (MediaData* aAudio) {
[this, self] (MediaData* aAudio) {
MOZ_ASSERT(aAudio);
mAudioDataRequest.Complete();
// audio->GetEndTime() is not always mono-increasing in chained ogg.
@ -3124,7 +3125,7 @@ MediaDecoderStateMachine::RequestAudioData()
aAudio->GetEndTime());
mStateObj->HandleAudioDecoded(aAudio);
},
[this] (const MediaResult& aError) {
[this, self] (const MediaResult& aError) {
SAMPLE_LOG("OnAudioNotDecoded aError=%" PRIu32, static_cast<uint32_t>(aError.Code()));
mAudioDataRequest.Complete();
switch (aError.Code()) {
@ -3158,9 +3159,10 @@ MediaDecoderStateMachine::RequestVideoData(bool aSkipToNextKeyframe,
aSkipToNextKeyframe, aCurrentTime.ToMicroseconds());
TimeStamp videoDecodeStartTime = TimeStamp::Now();
RefPtr<MediaDecoderStateMachine> self = this;
mReader->RequestVideoData(aSkipToNextKeyframe, aCurrentTime)->Then(
OwnerThread(), __func__,
[this, videoDecodeStartTime] (MediaData* aVideo) {
[this, self, videoDecodeStartTime] (MediaData* aVideo) {
MOZ_ASSERT(aVideo);
mVideoDataRequest.Complete();
// Handle abnormal or negative timestamps.
@ -3170,7 +3172,7 @@ MediaDecoderStateMachine::RequestVideoData(bool aSkipToNextKeyframe,
aVideo->GetEndTime());
mStateObj->HandleVideoDecoded(aVideo, videoDecodeStartTime);
},
[this] (const MediaResult& aError) {
[this, self] (const MediaResult& aError) {
SAMPLE_LOG("OnVideoNotDecoded aError=%" PRIu32 , static_cast<uint32_t>(aError.Code()));
mVideoDataRequest.Complete();
switch (aError.Code()) {
@ -3194,29 +3196,30 @@ MediaDecoderStateMachine::WaitForData(MediaData::Type aType)
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(aType == MediaData::AUDIO_DATA || aType == MediaData::VIDEO_DATA);
RefPtr<MediaDecoderStateMachine> self = this;
if (aType == MediaData::AUDIO_DATA) {
mReader->WaitForData(MediaData::AUDIO_DATA)->Then(
OwnerThread(), __func__,
[this] (MediaData::Type aType) {
mAudioWaitRequest.Complete();
[self] (MediaData::Type aType) {
self->mAudioWaitRequest.Complete();
MOZ_ASSERT(aType == MediaData::AUDIO_DATA);
mStateObj->HandleAudioWaited(aType);
self->mStateObj->HandleAudioWaited(aType);
},
[this] (const WaitForDataRejectValue& aRejection) {
mAudioWaitRequest.Complete();
DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
[self] (const WaitForDataRejectValue& aRejection) {
self->mAudioWaitRequest.Complete();
self->DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
})->Track(mAudioWaitRequest);
} else {
mReader->WaitForData(MediaData::VIDEO_DATA)->Then(
OwnerThread(), __func__,
[this] (MediaData::Type aType) {
mVideoWaitRequest.Complete();
[self] (MediaData::Type aType) {
self->mVideoWaitRequest.Complete();
MOZ_ASSERT(aType == MediaData::VIDEO_DATA);
mStateObj->HandleVideoWaited(aType);
self->mStateObj->HandleVideoWaited(aType);
},
[this] (const WaitForDataRejectValue& aRejection) {
mVideoWaitRequest.Complete();
DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
[self] (const WaitForDataRejectValue& aRejection) {
self->mVideoWaitRequest.Complete();
self->DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
})->Track(mVideoWaitRequest);
}
}
@ -3577,9 +3580,10 @@ MediaDecoderStateMachine::ScheduleStateMachineIn(int64_t aMicroseconds)
// It is OK to capture 'this' without causing UAF because the callback
// always happens before shutdown.
mDelayedScheduler.Ensure(target, [this] () {
mDelayedScheduler.CompleteRequest();
RunStateMachine();
RefPtr<MediaDecoderStateMachine> self = this;
mDelayedScheduler.Ensure(target, [self] () {
self->mDelayedScheduler.CompleteRequest();
self->RunStateMachine();
}, [] () {
MOZ_DIAGNOSTIC_ASSERT(false);
});
@ -3796,8 +3800,9 @@ MediaDecoderStateMachine::RequestDebugInfo()
{
using PromiseType = MediaDecoder::DebugInfoPromise;
RefPtr<PromiseType::Private> p = new PromiseType::Private(__func__);
OwnerThread()->Dispatch(NS_NewRunnableFunction([this, p] () {
p->Resolve(GetDebugInfo(), __func__);
RefPtr<MediaDecoderStateMachine> self = this;
OwnerThread()->Dispatch(NS_NewRunnableFunction([self, p] () {
p->Resolve(self->GetDebugInfo(), __func__);
}), AbstractThread::AssertDispatchSuccess, AbstractThread::TailDispatch);
return p.forget();
}

Просмотреть файл

@ -2295,23 +2295,23 @@ if (privileged) {
RefPtr<PledgeSourceSet> p = EnumerateDevicesImpl(windowID, videoType,
audioType, fake);
p->Then([this, onSuccess, onFailure, windowID, c, listener, askPermission,
RefPtr<MediaManager> self = this;
p->Then([self, onSuccess, onFailure, windowID, c, listener, askPermission,
prefs, isHTTPS, callID, principalInfo,
isChrome](SourceSet*& aDevices) mutable {
RefPtr<Refcountable<UniquePtr<SourceSet>>> devices(
new Refcountable<UniquePtr<SourceSet>>(aDevices)); // grab result
// Ensure that the captured 'this' pointer and our windowID are still good.
if (!MediaManager::Exists() ||
!nsGlobalWindow::GetInnerWindowWithId(windowID)) {
// Ensure that our windowID is still good.
if (!nsGlobalWindow::GetInnerWindowWithId(windowID)) {
return;
}
// Apply any constraints. This modifies the passed-in list.
RefPtr<PledgeChar> p2 = SelectSettings(c, isChrome, devices);
RefPtr<PledgeChar> p2 = self->SelectSettings(c, isChrome, devices);
p2->Then([this, onSuccess, onFailure, windowID, c,
p2->Then([self, onSuccess, onFailure, windowID, c,
listener, askPermission, prefs, isHTTPS, callID, principalInfo,
isChrome, devices](const char*& badConstraint) mutable {
@ -2359,13 +2359,13 @@ if (privileged) {
isChrome,
devices->release()));
// Store the task w/callbacks.
mActiveCallbacks.Put(callID, task.forget());
self->mActiveCallbacks.Put(callID, task.forget());
// Add a WindowID cross-reference so OnNavigation can tear things down
nsTArray<nsString>* array;
if (!mCallIds.Get(windowID, &array)) {
if (!self->mCallIds.Get(windowID, &array)) {
array = new nsTArray<nsString>();
mCallIds.Put(windowID, array);
self->mCallIds.Put(windowID, array);
}
array->AppendElement(callID);
@ -3002,7 +3002,9 @@ MediaManager::Shutdown()
// cleared until the lambda function clears it.
// note that this == sSingleton
RefPtr<MediaManager> that(sSingleton);
MOZ_ASSERT(this == sSingleton);
RefPtr<MediaManager> that = this;
// Release the backend (and call Shutdown()) from within the MediaManager thread
// Don't use MediaManager::PostTask() because we're sInShutdown=true here!
RefPtr<ShutdownTask> shutdown = new ShutdownTask(this,

Просмотреть файл

@ -70,9 +70,10 @@ public:
void Forget()
{
mAbstractMainThread->Dispatch(NS_NewRunnableFunction([this] () {
RefPtr<DecodedStreamGraphListener> self = this;
mAbstractMainThread->Dispatch(NS_NewRunnableFunction([self] () {
MOZ_ASSERT(NS_IsMainThread());
mFinishPromise.ResolveIfExists(true, __func__);
self->mFinishPromise.ResolveIfExists(true, __func__);
}));
MutexAutoLock lock(mMutex);
mStream = nullptr;

Просмотреть файл

@ -128,7 +128,8 @@ OggDemuxer::~OggDemuxer()
// If we were able to initialize our decoders, report whether we encountered
// a chained stream or not.
bool isChained = mIsChained;
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([=]() -> void {
RefPtr<OggDemuxer> self = this;
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([this, self, isChained]() -> void {
OGG_DEBUG("Reporting telemetry MEDIA_OGG_LOADED_IS_CHAINED=%d", isChained);
Telemetry::Accumulate(Telemetry::HistogramID::MEDIA_OGG_LOADED_IS_CHAINED, isChained);
});

Просмотреть файл

@ -284,9 +284,10 @@ CamerasChild::NumberOfCapabilities(CaptureEngine aCapEngine,
LOG((__PRETTY_FUNCTION__));
LOG(("NumberOfCapabilities for %s", deviceUniqueIdUTF8));
nsCString unique_id(deviceUniqueIdUTF8);
RefPtr<CamerasChild> self = this;
nsCOMPtr<nsIRunnable> runnable =
media::NewRunnableFrom([this, aCapEngine, unique_id]() -> nsresult {
if (this->SendNumberOfCapabilities(aCapEngine, unique_id)) {
media::NewRunnableFrom([self, aCapEngine, unique_id]() -> nsresult {
if (self->SendNumberOfCapabilities(aCapEngine, unique_id)) {
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -300,9 +301,10 @@ int
CamerasChild::NumberOfCaptureDevices(CaptureEngine aCapEngine)
{
LOG((__PRETTY_FUNCTION__));
RefPtr<CamerasChild> self = this;
nsCOMPtr<nsIRunnable> runnable =
media::NewRunnableFrom([this, aCapEngine]() -> nsresult {
if (this->SendNumberOfCaptureDevices(aCapEngine)) {
media::NewRunnableFrom([self, aCapEngine]() -> nsresult {
if (self->SendNumberOfCaptureDevices(aCapEngine)) {
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -328,9 +330,10 @@ int
CamerasChild::EnsureInitialized(CaptureEngine aCapEngine)
{
LOG((__PRETTY_FUNCTION__));
RefPtr<CamerasChild> self = this;
nsCOMPtr<nsIRunnable> runnable =
media::NewRunnableFrom([this, aCapEngine]() -> nsresult {
if (this->SendEnsureInitialized(aCapEngine)) {
media::NewRunnableFrom([self, aCapEngine]() -> nsresult {
if (self->SendEnsureInitialized(aCapEngine)) {
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -348,9 +351,10 @@ CamerasChild::GetCaptureCapability(CaptureEngine aCapEngine,
{
LOG(("GetCaptureCapability: %s %d", unique_idUTF8, capability_number));
nsCString unique_id(unique_idUTF8);
RefPtr<CamerasChild> self = this;
nsCOMPtr<nsIRunnable> runnable =
media::NewRunnableFrom([this, aCapEngine, unique_id, capability_number]() -> nsresult {
if (this->SendGetCaptureCapability(aCapEngine, unique_id, capability_number)) {
media::NewRunnableFrom([self, aCapEngine, unique_id, capability_number]() -> nsresult {
if (self->SendGetCaptureCapability(aCapEngine, unique_id, capability_number)) {
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -389,9 +393,10 @@ CamerasChild::GetCaptureDevice(CaptureEngine aCapEngine,
bool* scary)
{
LOG((__PRETTY_FUNCTION__));
RefPtr<CamerasChild> self = this;
nsCOMPtr<nsIRunnable> runnable =
media::NewRunnableFrom([this, aCapEngine, list_number]() -> nsresult {
if (this->SendGetCaptureDevice(aCapEngine, list_number)) {
media::NewRunnableFrom([self, aCapEngine, list_number]() -> nsresult {
if (self->SendGetCaptureDevice(aCapEngine, list_number)) {
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -433,9 +438,10 @@ CamerasChild::AllocateCaptureDevice(CaptureEngine aCapEngine,
{
LOG((__PRETTY_FUNCTION__));
nsCString unique_id(unique_idUTF8);
RefPtr<CamerasChild> self = this;
nsCOMPtr<nsIRunnable> runnable =
media::NewRunnableFrom([this, aCapEngine, unique_id, aPrincipalInfo]() -> nsresult {
if (this->SendAllocateCaptureDevice(aCapEngine, unique_id, aPrincipalInfo)) {
media::NewRunnableFrom([self, aCapEngine, unique_id, aPrincipalInfo]() -> nsresult {
if (self->SendAllocateCaptureDevice(aCapEngine, unique_id, aPrincipalInfo)) {
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -466,9 +472,10 @@ CamerasChild::ReleaseCaptureDevice(CaptureEngine aCapEngine,
const int capture_id)
{
LOG((__PRETTY_FUNCTION__));
RefPtr<CamerasChild> self = this;
nsCOMPtr<nsIRunnable> runnable =
media::NewRunnableFrom([this, aCapEngine, capture_id]() -> nsresult {
if (this->SendReleaseCaptureDevice(aCapEngine, capture_id)) {
media::NewRunnableFrom([self, aCapEngine, capture_id]() -> nsresult {
if (self->SendReleaseCaptureDevice(aCapEngine, capture_id)) {
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -517,9 +524,10 @@ CamerasChild::StartCapture(CaptureEngine aCapEngine,
webrtcCaps.rawType,
webrtcCaps.codecType,
webrtcCaps.interlaced);
RefPtr<CamerasChild> self = this;
nsCOMPtr<nsIRunnable> runnable =
media::NewRunnableFrom([this, aCapEngine, capture_id, capCap]() -> nsresult {
if (this->SendStartCapture(aCapEngine, capture_id, capCap)) {
media::NewRunnableFrom([self, aCapEngine, capture_id, capCap]() -> nsresult {
if (self->SendStartCapture(aCapEngine, capture_id, capCap)) {
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -532,9 +540,10 @@ int
CamerasChild::StopCapture(CaptureEngine aCapEngine, const int capture_id)
{
LOG((__PRETTY_FUNCTION__));
RefPtr<CamerasChild> self = this;
nsCOMPtr<nsIRunnable> runnable =
media::NewRunnableFrom([this, aCapEngine, capture_id]() -> nsresult {
if (this->SendStopCapture(aCapEngine, capture_id)) {
media::NewRunnableFrom([self, aCapEngine, capture_id]() -> nsresult {
if (self->SendStopCapture(aCapEngine, capture_id)) {
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -599,11 +608,12 @@ CamerasChild::ShutdownParent()
if (CamerasSingleton::Thread()) {
LOG(("Dispatching actor deletion"));
// Delete the parent actor.
RefPtr<CamerasChild> self = this;
RefPtr<Runnable> deleteRunnable =
// CamerasChild (this) will remain alive and is only deleted by the
// IPC layer when SendAllDone returns.
media::NewRunnableFrom([this]() -> nsresult {
Unused << this->SendAllDone();
media::NewRunnableFrom([self]() -> nsresult {
Unused << self->SendAllDone();
return NS_OK;
});
CamerasSingleton::Thread()->Dispatch(deleteRunnable, NS_DISPATCH_NORMAL);

Просмотреть файл

@ -316,10 +316,10 @@ MediaEngineRemoteVideoSource::SetLastCapability(
webrtc::CaptureCapability cap = aCapability;
RefPtr<MediaEngineRemoteVideoSource> that = this;
NS_DispatchToMainThread(media::NewRunnableFrom([this, that, cap]() mutable {
mSettings.mWidth.Value() = cap.width;
mSettings.mHeight.Value() = cap.height;
mSettings.mFrameRate.Value() = cap.maxFPS;
NS_DispatchToMainThread(media::NewRunnableFrom([that, cap]() mutable {
that->mSettings.mWidth.Value() = cap.width;
that->mSettings.mHeight.Value() = cap.height;
that->mSettings.mFrameRate.Value() = cap.maxFPS;
return NS_OK;
}));
}

Просмотреть файл

@ -373,10 +373,10 @@ MediaEngineWebRTCMicrophoneSource::SetLastPrefs(
RefPtr<MediaEngineWebRTCMicrophoneSource> that = this;
NS_DispatchToMainThread(media::NewRunnableFrom([this, that, aPrefs]() mutable {
mSettings.mEchoCancellation.Value() = aPrefs.mAecOn;
mSettings.mMozAutoGainControl.Value() = aPrefs.mAgcOn;
mSettings.mMozNoiseSuppression.Value() = aPrefs.mNoiseOn;
NS_DispatchToMainThread(media::NewRunnableFrom([that, aPrefs]() mutable {
that->mSettings.mEchoCancellation.Value() = aPrefs.mAecOn;
that->mSettings.mMozAutoGainControl.Value() = aPrefs.mAgcOn;
that->mSettings.mMozNoiseSuppression.Value() = aPrefs.mNoiseOn;
return NS_OK;
}));
}