LCOV - code coverage report
Current view: top level - dom/media - MediaDevices.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 127 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 40 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       3             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "mozilla/dom/MediaDevices.h"
       6             : #include "mozilla/dom/MediaStreamBinding.h"
       7             : #include "mozilla/dom/MediaDeviceInfo.h"
       8             : #include "mozilla/dom/MediaDevicesBinding.h"
       9             : #include "mozilla/dom/Promise.h"
      10             : #include "mozilla/MediaManager.h"
      11             : #include "MediaTrackConstraints.h"
      12             : #include "nsIEventTarget.h"
      13             : #include "nsIScriptGlobalObject.h"
      14             : #include "nsIPermissionManager.h"
      15             : #include "nsPIDOMWindow.h"
      16             : #include "nsQueryObject.h"
      17             : 
      18             : #define DEVICECHANGE_HOLD_TIME_IN_MS 1000
      19             : 
      20             : namespace mozilla {
      21             : namespace dom {
      22             : 
      23             : class FuzzTimerCallBack final : public nsITimerCallback
      24             : {
      25           0 :   ~FuzzTimerCallBack() {}
      26             : 
      27             : public:
      28           0 :   explicit FuzzTimerCallBack(MediaDevices* aMediaDevices) : mMediaDevices(aMediaDevices) {}
      29             : 
      30             :   NS_DECL_ISUPPORTS
      31             : 
      32           0 :   NS_IMETHOD Notify(nsITimer* aTimer) final
      33             :   {
      34           0 :     mMediaDevices->DispatchTrustedEvent(NS_LITERAL_STRING("devicechange"));
      35           0 :     return NS_OK;
      36             :   }
      37             : 
      38             : private:
      39             :   nsCOMPtr<MediaDevices> mMediaDevices;
      40             : };
      41             : 
      42           0 : NS_IMPL_ISUPPORTS(FuzzTimerCallBack, nsITimerCallback)
      43             : 
      44             : class MediaDevices::GumResolver : public nsIDOMGetUserMediaSuccessCallback
      45             : {
      46             : public:
      47             :   NS_DECL_ISUPPORTS
      48             : 
      49           0 :   explicit GumResolver(Promise* aPromise) : mPromise(aPromise) {}
      50             : 
      51             :   NS_IMETHOD
      52           0 :   OnSuccess(nsISupports* aStream) override
      53             :   {
      54           0 :     RefPtr<DOMMediaStream> stream = do_QueryObject(aStream);
      55           0 :     if (!stream) {
      56           0 :       return NS_ERROR_FAILURE;
      57             :     }
      58           0 :     mPromise->MaybeResolve(stream);
      59           0 :     return NS_OK;
      60             :   }
      61             : 
      62             : private:
      63           0 :   virtual ~GumResolver() {}
      64             :   RefPtr<Promise> mPromise;
      65             : };
      66             : 
      67             : class MediaDevices::EnumDevResolver : public nsIGetUserMediaDevicesSuccessCallback
      68             : {
      69             : public:
      70             :   NS_DECL_ISUPPORTS
      71             : 
      72           0 :   EnumDevResolver(Promise* aPromise, uint64_t aWindowId)
      73           0 :   : mPromise(aPromise), mWindowId(aWindowId) {}
      74             : 
      75             :   NS_IMETHOD
      76           0 :   OnSuccess(nsIVariant* aDevices) override
      77             :   {
      78             :     // Cribbed from MediaPermissionGonk.cpp
      79             : 
      80             :     // Create array for nsIMediaDevice
      81           0 :     nsTArray<nsCOMPtr<nsIMediaDevice>> devices;
      82             :     // Contain the fumes
      83             :     {
      84             :       uint16_t vtype;
      85           0 :       nsresult rv = aDevices->GetDataType(&vtype);
      86           0 :       NS_ENSURE_SUCCESS(rv, rv);
      87           0 :       if (vtype != nsIDataType::VTYPE_EMPTY_ARRAY) {
      88             :         nsIID elementIID;
      89             :         uint16_t elementType;
      90             :         void* rawArray;
      91             :         uint32_t arrayLen;
      92           0 :         rv = aDevices->GetAsArray(&elementType, &elementIID, &arrayLen, &rawArray);
      93           0 :         NS_ENSURE_SUCCESS(rv, rv);
      94           0 :         if (elementType != nsIDataType::VTYPE_INTERFACE) {
      95           0 :           free(rawArray);
      96           0 :           return NS_ERROR_FAILURE;
      97             :         }
      98             : 
      99           0 :         nsISupports **supportsArray = reinterpret_cast<nsISupports **>(rawArray);
     100           0 :         for (uint32_t i = 0; i < arrayLen; ++i) {
     101           0 :           nsCOMPtr<nsIMediaDevice> device(do_QueryInterface(supportsArray[i]));
     102           0 :           devices.AppendElement(device);
     103           0 :           NS_IF_RELEASE(supportsArray[i]); // explicitly decrease refcount for rawptr
     104             :         }
     105           0 :         free(rawArray); // explicitly free memory from nsIVariant::GetAsArray
     106             :       }
     107             :     }
     108           0 :     nsTArray<RefPtr<MediaDeviceInfo>> infos;
     109           0 :     for (auto& device : devices) {
     110           0 :       nsString type;
     111           0 :       device->GetType(type);
     112           0 :       bool isVideo = type.EqualsLiteral("video");
     113           0 :       bool isAudio = type.EqualsLiteral("audio");
     114           0 :       if (isVideo || isAudio) {
     115           0 :         MediaDeviceKind kind = isVideo ?
     116           0 :             MediaDeviceKind::Videoinput : MediaDeviceKind::Audioinput;
     117           0 :         nsString id;
     118           0 :         nsString name;
     119           0 :         device->GetId(id);
     120             :         // Include name only if page currently has a gUM stream active or
     121             :         // persistent permissions (audio or video) have been granted
     122           0 :         if (MediaManager::Get()->IsActivelyCapturingOrHasAPermission(mWindowId) ||
     123           0 :             Preferences::GetBool("media.navigator.permission.disabled", false)) {
     124           0 :           device->GetName(name);
     125             :         }
     126           0 :         RefPtr<MediaDeviceInfo> info = new MediaDeviceInfo(id, kind, name);
     127           0 :         infos.AppendElement(info);
     128             :       }
     129             :     }
     130           0 :     mPromise->MaybeResolve(infos);
     131           0 :     return NS_OK;
     132             :   }
     133             : 
     134             : private:
     135           0 :   virtual ~EnumDevResolver() {}
     136             :   RefPtr<Promise> mPromise;
     137             :   uint64_t mWindowId;
     138             : };
     139             : 
     140             : class MediaDevices::GumRejecter : public nsIDOMGetUserMediaErrorCallback
     141             : {
     142             : public:
     143             :   NS_DECL_ISUPPORTS
     144             : 
     145           0 :   explicit GumRejecter(Promise* aPromise) : mPromise(aPromise) {}
     146             : 
     147             :   NS_IMETHOD
     148           0 :   OnError(nsISupports* aError) override
     149             :   {
     150           0 :     RefPtr<MediaStreamError> error = do_QueryObject(aError);
     151           0 :     if (!error) {
     152           0 :       return NS_ERROR_FAILURE;
     153             :     }
     154           0 :     mPromise->MaybeReject(error);
     155           0 :     return NS_OK;
     156             :   }
     157             : 
     158             : private:
     159           0 :   virtual ~GumRejecter() {}
     160             :   RefPtr<Promise> mPromise;
     161             : };
     162             : 
     163           0 : MediaDevices::~MediaDevices()
     164             : {
     165           0 :   MediaManager* mediamanager = MediaManager::GetIfExists();
     166           0 :   if (mediamanager) {
     167           0 :     mediamanager->RemoveDeviceChangeCallback(this);
     168             :   }
     169           0 : }
     170             : 
     171           0 : NS_IMPL_ISUPPORTS(MediaDevices::GumResolver, nsIDOMGetUserMediaSuccessCallback)
     172           0 : NS_IMPL_ISUPPORTS(MediaDevices::EnumDevResolver, nsIGetUserMediaDevicesSuccessCallback)
     173           0 : NS_IMPL_ISUPPORTS(MediaDevices::GumRejecter, nsIDOMGetUserMediaErrorCallback)
     174             : 
     175             : already_AddRefed<Promise>
     176           0 : MediaDevices::GetUserMedia(const MediaStreamConstraints& aConstraints,
     177             :                            CallerType aCallerType,
     178             :                            ErrorResult &aRv)
     179             : {
     180           0 :   nsPIDOMWindowInner* window = GetOwner();
     181           0 :   nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(window);
     182           0 :   RefPtr<Promise> p = Promise::Create(go, aRv);
     183           0 :   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
     184             : 
     185           0 :   RefPtr<GumResolver> resolver = new GumResolver(p);
     186           0 :   RefPtr<GumRejecter> rejecter = new GumRejecter(p);
     187             : 
     188           0 :   aRv = MediaManager::Get()->GetUserMedia(window, aConstraints,
     189             :                                           resolver, rejecter,
     190           0 :                                           aCallerType);
     191           0 :   return p.forget();
     192             : }
     193             : 
     194             : already_AddRefed<Promise>
     195           0 : MediaDevices::EnumerateDevices(ErrorResult &aRv)
     196             : {
     197           0 :   nsPIDOMWindowInner* window = GetOwner();
     198           0 :   nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(window);
     199           0 :   RefPtr<Promise> p = Promise::Create(go, aRv);
     200           0 :   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
     201             : 
     202           0 :   RefPtr<EnumDevResolver> resolver = new EnumDevResolver(p, window->WindowID());
     203           0 :   RefPtr<GumRejecter> rejecter = new GumRejecter(p);
     204             : 
     205           0 :   aRv = MediaManager::Get()->EnumerateDevices(window, resolver, rejecter);
     206           0 :   return p.forget();
     207             : }
     208             : 
     209           0 : NS_IMPL_ADDREF_INHERITED(MediaDevices, DOMEventTargetHelper)
     210           0 : NS_IMPL_RELEASE_INHERITED(MediaDevices, DOMEventTargetHelper)
     211           0 : NS_INTERFACE_MAP_BEGIN(MediaDevices)
     212           0 :   NS_INTERFACE_MAP_ENTRY(MediaDevices)
     213           0 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
     214             : 
     215             : void
     216           0 : MediaDevices::OnDeviceChange()
     217             : {
     218           0 :   MOZ_ASSERT(NS_IsMainThread());
     219           0 :   nsresult rv = CheckInnerWindowCorrectness();
     220           0 :   if (NS_FAILED(rv)) {
     221           0 :     MOZ_ASSERT(false);
     222             :     return;
     223             :   }
     224             : 
     225           0 :   if (!(MediaManager::Get()->IsActivelyCapturingOrHasAPermission(GetOwner()->WindowID()) ||
     226           0 :     Preferences::GetBool("media.navigator.permission.disabled", false))) {
     227           0 :     return;
     228             :   }
     229             : 
     230           0 :   if (!mFuzzTimer)
     231             :   {
     232           0 :     mFuzzTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
     233             :   }
     234             : 
     235           0 :   if (!mFuzzTimer) {
     236           0 :     MOZ_ASSERT(false);
     237             :     return;
     238             :   }
     239             : 
     240           0 :   mFuzzTimer->Cancel();
     241           0 :   RefPtr<FuzzTimerCallBack> cb = new FuzzTimerCallBack(this);
     242           0 :   mFuzzTimer->InitWithCallback(cb, DEVICECHANGE_HOLD_TIME_IN_MS, nsITimer::TYPE_ONE_SHOT);
     243             : }
     244             : 
     245             : mozilla::dom::EventHandlerNonNull*
     246           0 : MediaDevices::GetOndevicechange()
     247             : {
     248           0 :   if (NS_IsMainThread()) {
     249           0 :     return GetEventHandler(nsGkAtoms::ondevicechange, EmptyString());
     250             :   }
     251           0 :   return GetEventHandler(nullptr, NS_LITERAL_STRING("devicechange"));
     252             : }
     253             : 
     254             : void
     255           0 : MediaDevices::SetOndevicechange(mozilla::dom::EventHandlerNonNull* aCallback)
     256             : {
     257           0 :   if (NS_IsMainThread()) {
     258           0 :     SetEventHandler(nsGkAtoms::ondevicechange, EmptyString(), aCallback);
     259             :   } else {
     260           0 :     SetEventHandler(nullptr, NS_LITERAL_STRING("devicechange"), aCallback);
     261             :   }
     262             : 
     263           0 :   MediaManager::Get()->AddDeviceChangeCallback(this);
     264           0 : }
     265             : 
     266             : nsresult
     267           0 : MediaDevices::AddEventListener(const nsAString& aType,
     268             :   nsIDOMEventListener* aListener,
     269             :   bool aUseCapture, bool aWantsUntrusted,
     270             :   uint8_t optional_argc)
     271             : {
     272           0 :   MediaManager::Get()->AddDeviceChangeCallback(this);
     273             : 
     274           0 :   return mozilla::DOMEventTargetHelper::AddEventListener(aType, aListener,
     275             :     aUseCapture,
     276             :     aWantsUntrusted,
     277           0 :     optional_argc);
     278             : }
     279             : 
     280             : void
     281           0 : MediaDevices::AddEventListener(const nsAString& aType,
     282             :   dom::EventListener* aListener,
     283             :   const dom::AddEventListenerOptionsOrBoolean& aOptions,
     284             :   const dom::Nullable<bool>& aWantsUntrusted,
     285             :   ErrorResult& aRv)
     286             : {
     287           0 :   MediaManager::Get()->AddDeviceChangeCallback(this);
     288             : 
     289           0 :   return mozilla::DOMEventTargetHelper::AddEventListener(aType, aListener,
     290             :     aOptions,
     291             :     aWantsUntrusted,
     292           0 :     aRv);
     293             : }
     294             : 
     295             : JSObject*
     296           0 : MediaDevices::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     297             : {
     298           0 :   return MediaDevicesBinding::Wrap(aCx, this, aGivenProto);
     299             : }
     300             : 
     301             : } // namespace dom
     302             : } // namespace mozilla

Generated by: LCOV version 1.13