diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index ceba1966cc7..ed41031a8a1 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -6,9 +6,11 @@ #include "MediaStreamGraph.h" #include "GetUserMediaRequest.h" +#include "nsHashPropertyBag.h" #ifdef MOZ_WIDGET_GONK #include "nsIAudioManager.h" #endif +#include "nsIAppsService.h" #include "nsIDOMFile.h" #include "nsIEventTarget.h" #include "nsIUUIDGenerator.h" @@ -19,7 +21,8 @@ #include "nsIDocument.h" #include "nsISupportsPrimitives.h" #include "nsIInterfaceRequestorUtils.h" -#include "mozilla/dom/ContentChild.h" +#include "nsIScriptSecurityManager.h" +#include "mozilla/dom/TabChild.h" #include "mozilla/dom/MediaStreamTrackBinding.h" #include "mozilla/dom/GetUserMediaRequestBinding.h" @@ -138,6 +141,45 @@ static nsresult ValidateTrackConstraints( return NS_OK; } +static already_AddRefed +CreateRecordingDeviceEventsSubject(nsPIDOMWindow* aWindow, + const bool aIsAudio, + const bool aIsVideo) +{ + MOZ_ASSERT(aWindow); + + nsRefPtr props = new nsHashPropertyBag(); + props->SetPropertyAsBool(NS_LITERAL_STRING("isAudio"), aIsAudio); + props->SetPropertyAsBool(NS_LITERAL_STRING("isVideo"), aIsVideo); + + nsCOMPtr docShell = aWindow->GetDocShell(); + if (docShell) { + bool isApp; + DebugOnly rv = docShell->GetIsApp(&isApp); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + nsString requestURL; + if (isApp) { + rv = docShell->GetAppManifestURL(requestURL); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + } else { + nsCString pageURL; + nsCOMPtr docURI = aWindow->GetDocumentURI(); + MOZ_ASSERT(docURI); + + rv = docURI->GetSpec(pageURL); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + requestURL = NS_ConvertUTF8toUTF16(pageURL); + } + + props->SetPropertyAsAString(NS_LITERAL_STRING("requestURL"), requestURL); + props->SetPropertyAsBool(NS_LITERAL_STRING("isApp"), isApp); + } + + return props.forget(); +} + /** * Send an error back to content. The error is the form a string. * Do this only on the main thread. The success callback is also passed here @@ -584,7 +626,7 @@ public: nsRefPtr runnable( new MediaOperationRunnable(MEDIA_START, mListener, trackunion, tracksAvailableCallback, - mAudioSource, mVideoSource, false)); + mAudioSource, mVideoSource, false, mWindowID)); mediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); #ifdef MOZ_WEBRTC @@ -1730,7 +1772,7 @@ GetUserMediaCallbackMediaStreamListener::Invalidate() runnable = new MediaOperationRunnable(MEDIA_STOP, this, nullptr, nullptr, mAudioSource, mVideoSource, - mFinished); + mFinished, mWindowID); mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); } @@ -1787,13 +1829,20 @@ GetUserMediaNotificationEvent::Run() } break; } - obs->NotifyObservers(nullptr, + + nsCOMPtr window = nsGlobalWindow::GetInnerWindowWithId(mWindowID); + MOZ_ASSERT(window); + + nsRefPtr props = + CreateRecordingDeviceEventsSubject(window, mIsAudio, mIsVideo); + + obs->NotifyObservers(static_cast(props), "recording-device-events", msg.get()); // Forward recording events to parent process. // The events are gathered in chrome process and used for recording indicator if (XRE_GetProcessType() != GeckoProcessType_Default) { - unused << dom::ContentChild::GetSingleton()->SendRecordingDeviceEvents(msg); + unused << dom::TabChild::GetFrom(window)->SendRecordingDeviceEvents(msg, mIsAudio, mIsVideo); } return NS_OK; } diff --git a/dom/media/MediaManager.h b/dom/media/MediaManager.h index df135eb7a72..6e00da0079c 100644 --- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -204,14 +204,17 @@ class GetUserMediaNotificationEvent: public nsRunnable STOPPING }; GetUserMediaNotificationEvent(GetUserMediaCallbackMediaStreamListener* aListener, - GetUserMediaStatus aStatus) - : mListener(aListener), mStatus(aStatus) {} + GetUserMediaStatus aStatus, + bool aIsAudio, bool aIsVideo, uint64_t aWindowID) + : mListener(aListener) , mStatus(aStatus) , mIsAudio(aIsAudio) + , mIsVideo(aIsVideo), mWindowID(aWindowID) {} GetUserMediaNotificationEvent(GetUserMediaStatus aStatus, already_AddRefed aStream, - DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback) + DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback, + bool aIsAudio, bool aIsVideo, uint64_t aWindowID) : mStream(aStream), mOnTracksAvailableCallback(aOnTracksAvailableCallback), - mStatus(aStatus) {} + mStatus(aStatus), mIsAudio(aIsAudio), mIsVideo(aIsVideo), mWindowID(aWindowID) {} virtual ~GetUserMediaNotificationEvent() { @@ -224,6 +227,9 @@ class GetUserMediaNotificationEvent: public nsRunnable nsRefPtr mStream; nsAutoPtr mOnTracksAvailableCallback; GetUserMediaStatus mStatus; + bool mIsAudio; + bool mIsVideo; + uint64_t mWindowID; }; typedef enum { @@ -244,7 +250,8 @@ public: DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback, MediaEngineSource* aAudioSource, MediaEngineSource* aVideoSource, - bool aNeedsFinish) + bool aNeedsFinish, + uint64_t aWindowID) : mType(aType) , mStream(aStream) , mOnTracksAvailableCallback(aOnTracksAvailableCallback) @@ -252,6 +259,7 @@ public: , mVideoSource(aVideoSource) , mListener(aListener) , mFinish(aNeedsFinish) + , mWindowID(aWindowID) {} ~MediaOperationRunnable() @@ -303,7 +311,10 @@ public: nsRefPtr event = new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STARTING, mStream.forget(), - mOnTracksAvailableCallback.forget()); + mOnTracksAvailableCallback.forget(), + mAudioSource != nullptr, + mVideoSource != nullptr, + mWindowID); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); } break; @@ -324,7 +335,11 @@ public: source->Finish(); } nsRefPtr event = - new GetUserMediaNotificationEvent(mListener, GetUserMediaNotificationEvent::STOPPING); + new GetUserMediaNotificationEvent(mListener, + GetUserMediaNotificationEvent::STOPPING, + mAudioSource != nullptr, + mVideoSource != nullptr, + mWindowID); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); } @@ -345,6 +360,7 @@ private: nsRefPtr mVideoSource; // threadsafe nsRefPtr mListener; // threadsafe bool mFinish; + uint64_t mWindowID; }; typedef nsTArray > StreamListeners;