Bug 853356 - Part2 Add MediaPermissionGonk.h and MediaPermissionGonk.cpp to implement ContentPermissionPrompt. r=jesup
authorAlfredo Yang <ayang@mozilla.com>
Fri, 06 Dec 2013 17:38:51 -0500
changeset 175089 5a019e26c6b2a82ffd5482f18e08b64081cf7e46
parent 175088 3fd07d5561b721f59422fd54772425de2724b772
child 175090 a72c03a07567922c6025b6aa111ae9854ca60863
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs853356
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 853356 - Part2 Add MediaPermissionGonk.h and MediaPermissionGonk.cpp to implement ContentPermissionPrompt. r=jesup
content/media/webrtc/MediaEngine.h
dom/media/MediaManager.cpp
dom/media/MediaManager.h
dom/media/MediaPermissionGonk.cpp
--- a/content/media/webrtc/MediaEngine.h
+++ b/content/media/webrtc/MediaEngine.h
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MEDIAENGINE_H_
 #define MEDIAENGINE_H_
 
+#include "mozilla/RefPtr.h"
 #include "nsIDOMFile.h"
 #include "DOMMediaStream.h"
 #include "MediaStreamGraph.h"
 
 namespace mozilla {
 
 /**
  * Abstract interface for managing audio and video devices. Each platform
@@ -30,17 +31,17 @@ enum MediaEngineState {
 };
 
 // We only support 1 audio and 1 video track for now.
 enum {
   kVideoTrack = 1,
   kAudioTrack = 2
 };
 
-class MediaEngine
+class MediaEngine : public RefCounted<MediaEngine>
 {
 public:
   virtual ~MediaEngine() {}
 
   static const int DEFAULT_VIDEO_FPS = 30;
   static const int DEFAULT_VIDEO_MIN_FPS = 10;
   static const int DEFAULT_VIDEO_WIDTH = 640;
   static const int DEFAULT_VIDEO_HEIGHT = 480;
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -36,17 +36,17 @@
 #include "mozilla/Preferences.h"
 
 /* Using WebRTC backend on Desktops (Mac, Windows, Linux), otherwise default */
 #include "MediaEngineDefault.h"
 #if defined(MOZ_WEBRTC)
 #include "MediaEngineWebRTC.h"
 #endif
 
-#ifdef MOZ_WIDGET_GONK
+#ifdef MOZ_B2G
 #include "MediaPermissionGonk.h"
 #endif
 
 // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
 // GetTickCount() and conflicts with MediaStream::GetCurrentTime.
 #ifdef GetCurrentTime
 #undef GetCurrentTime
 #endif
@@ -751,17 +751,17 @@ public:
     MediaEnginePrefs &aPrefs)
     : mConstraints(aConstraints)
     , mSuccess(aSuccess)
     , mError(aError)
     , mWindowID(aWindowID)
     , mListener(aListener)
     , mPrefs(aPrefs)
     , mDeviceChosen(false)
-    , mBackendChosen(false)
+    , mBackend(nullptr)
     , mManager(MediaManager::GetInstance())
   {}
 
   /**
    * The caller can also choose to provide their own backend instead of
    * using the one provided by MediaManager::GetBackend.
    */
   GetUserMediaRunnable(
@@ -773,40 +773,37 @@ public:
     MediaEngine* aBackend)
     : mConstraints(aConstraints)
     , mSuccess(aSuccess)
     , mError(aError)
     , mWindowID(aWindowID)
     , mListener(aListener)
     , mPrefs(aPrefs)
     , mDeviceChosen(false)
-    , mBackendChosen(true)
     , mBackend(aBackend)
     , mManager(MediaManager::GetInstance())
   {}
 
   ~GetUserMediaRunnable() {
-    if (mBackendChosen) {
-      delete mBackend;
-    }
   }
 
   NS_IMETHOD
   Run()
   {
     NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
 
+    MediaEngine* backend = mBackend;
     // Was a backend provided?
-    if (!mBackendChosen) {
-      mBackend = mManager->GetBackend(mWindowID);
+    if (!backend) {
+      backend = mManager->GetBackend(mWindowID);
     }
 
     // Was a device provided?
     if (!mDeviceChosen) {
-      nsresult rv = SelectDevice();
+      nsresult rv = SelectDevice(backend);
       if (rv != NS_OK) {
         return rv;
       }
     }
 
     // It is an error if audio or video are requested along with picture.
     if (mConstraints.mPicture && (mConstraints.mAudio || mConstraints.mVideo)) {
       NS_DispatchToMainThread(new ErrorCallbackRunnable(
@@ -868,34 +865,34 @@ public:
   SetVideoDevice(MediaDevice* aVideoDevice)
   {
     mVideoDevice = aVideoDevice;
     mDeviceChosen = true;
     return NS_OK;
   }
 
   nsresult
-  SelectDevice()
+  SelectDevice(MediaEngine* backend)
   {
     if (mConstraints.mPicture || mConstraints.mVideo) {
-      ScopedDeletePtr<SourceSet> sources (GetSources(mBackend,
+      ScopedDeletePtr<SourceSet> sources (GetSources(backend,
           mConstraints.mVideom, &MediaEngine::EnumerateVideoDevices));
 
       if (!sources->Length()) {
         NS_DispatchToMainThread(new ErrorCallbackRunnable(
           mSuccess, mError, NS_LITERAL_STRING("NO_DEVICES_FOUND"), mWindowID));
         return NS_ERROR_FAILURE;
       }
       // Pick the first available device.
       mVideoDevice = do_QueryObject((*sources)[0]);
       LOG(("Selected video device"));
     }
 
     if (mConstraints.mAudio) {
-      ScopedDeletePtr<SourceSet> sources (GetSources(mBackend,
+      ScopedDeletePtr<SourceSet> sources (GetSources(backend,
           mConstraints.mAudiom, &MediaEngine::EnumerateAudioDevices));
 
       if (!sources->Length()) {
         NS_DispatchToMainThread(new ErrorCallbackRunnable(
           mSuccess, mError, NS_LITERAL_STRING("NO_DEVICES_FOUND"), mWindowID));
         return NS_ERROR_FAILURE;
       }
       // Pick the first available device.
@@ -979,19 +976,18 @@ private:
   already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
   uint64_t mWindowID;
   nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
   nsRefPtr<MediaDevice> mAudioDevice;
   nsRefPtr<MediaDevice> mVideoDevice;
   MediaEnginePrefs mPrefs;
 
   bool mDeviceChosen;
-  bool mBackendChosen;
 
-  MediaEngine* mBackend;
+  RefPtr<MediaEngine> mBackend;
   nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
 };
 
 /**
  * Similar to GetUserMediaRunnable, but used for the chrome-only
  * GetUserMediaDevices function. Enumerates a list of audio & video devices,
  * wraps them up in nsIMediaDevice objects and returns it to the success
  * callback.
@@ -1259,20 +1255,20 @@ MediaManager::GetUserMedia(JSContext* aC
   }
 #endif
 
   static bool created = false;
   if (!created) {
     // Force MediaManager to startup before we try to access it from other threads
     // Hack: should init singleton earlier unless it's expensive (mem or CPU)
     (void) MediaManager::Get();
-#ifdef MOZ_WIDGET_GONK
+#ifdef MOZ_B2G
     // Initialize MediaPermissionManager before send out any permission request.
     (void) MediaPermissionManager::GetInstance();
-#endif //MOZ_WIDGET_GONK
+#endif //MOZ_B2G
   }
 
   // Store the WindowID in a hash table and mark as active. The entry is removed
   // when this window is closed or navigated away from.
   uint64_t windowID = aWindow->WindowID();
   nsRefPtr<GetUserMediaRunnable> gUMRunnable;
   // This is safe since we're on main-thread, and the windowlist can only
   // be invalidated from the main-thread (see OnNavigation)
@@ -1405,21 +1401,21 @@ MediaEngine*
 MediaManager::GetBackend(uint64_t aWindowId)
 {
   // Plugin backends as appropriate. The default engine also currently
   // includes picture support for Android.
   // This IS called off main-thread.
   MutexAutoLock lock(mMutex);
   if (!mBackend) {
 #if defined(MOZ_WEBRTC)
-  #ifndef MOZ_B2G_CAMERA
+#ifndef MOZ_B2G_CAMERA
     mBackend = new MediaEngineWebRTC();
-  #else
+#else
     mBackend = new MediaEngineWebRTC(mCameraManager, aWindowId);
-  #endif
+#endif
 #else
     mBackend = new MediaEngineDefault();
 #endif
   }
   return mBackend;
 }
 
 void
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -506,35 +506,33 @@ private:
 
   void GetPref(nsIPrefBranch *aBranch, const char *aPref,
                const char *aData, int32_t *aVal);
   void GetPrefs(nsIPrefBranch *aBranch, const char *aData);
 
   // Make private because we want only one instance of this class
   MediaManager();
 
-  ~MediaManager() {
-    delete mBackend;
-  }
+  ~MediaManager() {}
 
   nsresult MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVideo,
                                            bool* aAudio);
 
   void StopMediaStreams();
 
   // ONLY access from MainThread so we don't need to lock
   WindowTable mActiveWindows;
   nsRefPtrHashtable<nsStringHashKey, nsRunnable> mActiveCallbacks;
   // Always exists
   nsCOMPtr<nsIThread> mMediaThread;
 
   Mutex mMutex;
   // protected with mMutex:
-  MediaEngine* mBackend;
+  RefPtr<MediaEngine> mBackend;
 
   static StaticRefPtr<MediaManager> sSingleton;
 
-#ifdef MOZ_WIDGET_GONK
+#ifdef MOZ_B2G_CAMERA
   nsRefPtr<nsDOMCameraManager> mCameraManager;
 #endif
 };
 
 } // namespace mozilla
--- a/dom/media/MediaPermissionGonk.cpp
+++ b/dom/media/MediaPermissionGonk.cpp
@@ -15,24 +15,46 @@
 #include "nsTArray.h"
 #include "GetUserMediaRequest.h"
 #include "PCOMContentPermissionRequestChild.h"
 #include "mozilla/dom/PBrowserChild.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/MediaStreamTrackBinding.h"
 #include "nsISupportsPrimitives.h"
 #include "nsServiceManagerUtils.h"
+#include "nsArrayUtils.h"
+#include "nsContentPermissionHelper.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 
 #define AUDIO_PERMISSION_NAME "audio-capture"
+#define VIDEO_PERMISSION_NAME "video-capture"
+
+using namespace mozilla::dom;
 
 namespace mozilla {
 
 static MediaPermissionManager *gMediaPermMgr = nullptr;
 
+static uint32_t
+ConvertArrayToPermissionRequest(nsIArray* aSrcArray,
+                                nsTArray<PermissionRequest>& aDesArray)
+{
+  uint32_t len = 0;
+  aSrcArray->GetLength(&len);
+  for (uint32_t i = 0; i < len; i++) {
+    nsCOMPtr<nsIContentPermissionType> cpt = do_QueryElementAt(aSrcArray, i);
+    nsAutoCString type;
+    nsAutoCString access;
+    cpt->GetType(type);
+    cpt->GetAccess(access);
+    aDesArray.AppendElement(PermissionRequest(type, access));
+  }
+  return len;
+}
+
 // Helper function for notifying permission granted
 static nsresult
 NotifyPermissionAllow(const nsAString &aCallID, nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
 {
   nsresult rv;
   nsCOMPtr<nsISupportsArray> array;
   rv = NS_NewISupportsArray(getter_AddRefs(array));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -88,77 +110,85 @@ public:
   // It will be called when prompt dismissed.
   virtual bool Recv__delete__(const bool &allow) MOZ_OVERRIDE;
   virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
 
   already_AddRefed<nsPIDOMWindow> GetOwner();
 
 private:
   bool mAudio; // Request for audio permission
+  bool mVideo; // Request for video permission
   nsRefPtr<dom::GetUserMediaRequest> mRequest;
   nsTArray<nsCOMPtr<nsIMediaDevice> > mDevices; // candiate device list
 };
 
 // MediaPermissionRequest
 NS_IMPL_ISUPPORTS1(MediaPermissionRequest, nsIContentPermissionRequest)
 
 MediaPermissionRequest::MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest> &aRequest,
                                                nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
   : mRequest(aRequest)
 {
   dom::MediaStreamConstraintsInternal constraints;
   mRequest->GetConstraints(constraints);
 
   mAudio = constraints.mAudio;
+  mVideo = constraints.mVideo;
 
   for (uint32_t i = 0; i < aDevices.Length(); ++i) {
     nsCOMPtr<nsIMediaDevice> device(aDevices[i]);
     nsAutoString deviceType;
     device->GetType(deviceType);
     if (mAudio && deviceType.EqualsLiteral("audio")) {
       mDevices.AppendElement(device);
     }
+    if (mVideo && deviceType.EqualsLiteral("video")) {
+      mDevices.AppendElement(device);
+    }
   }
 }
 
 // nsIContentPermissionRequest methods
 NS_IMETHODIMP
+MediaPermissionRequest::GetTypes(nsIArray** aTypes)
+{
+  nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
+  if (mAudio) {
+    nsCOMPtr<ContentPermissionType> AudioType =
+      new ContentPermissionType(NS_LITERAL_CSTRING(AUDIO_PERMISSION_NAME),
+                                NS_LITERAL_CSTRING("unused"));
+    types->AppendElement(AudioType, false);
+  }
+  if (mVideo) {
+    nsCOMPtr<ContentPermissionType> VideoType =
+      new ContentPermissionType(NS_LITERAL_CSTRING(VIDEO_PERMISSION_NAME),
+                                NS_LITERAL_CSTRING("unused"));
+    types->AppendElement(VideoType, false);
+  }
+  NS_IF_ADDREF(*aTypes = types);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 MediaPermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal)
 {
   NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mRequest->GetParentObject());
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
 
   NS_ADDREF(*aRequestingPrincipal = doc->NodePrincipal());
   return NS_OK;
 }
 
 NS_IMETHODIMP
-MediaPermissionRequest::GetType(nsACString &aType)
-{
-  if (mAudio) {
-    aType = AUDIO_PERMISSION_NAME;
-    return NS_OK;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-MediaPermissionRequest::GetAccess(nsACString &aAccess)
-{
-  aAccess = "unused";
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 MediaPermissionRequest::GetWindow(nsIDOMWindow** aRequestingWindow)
 {
   NS_ENSURE_ARG_POINTER(aRequestingWindow);
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mRequest->GetParentObject());
   window.forget(aRequestingWindow);
   return NS_OK;
 }
 
@@ -273,32 +303,30 @@ MediaDeviceSuccessCallback::DoPrompt(nsR
     nsresult rv;
 
     nsCOMPtr<nsPIDOMWindow> window(req->GetOwner());
     NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
     dom::TabChild* child = dom::TabChild::GetFrom(window->GetDocShell());
     NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
 
-    nsAutoCString type;
-    rv = req->GetType(type);
+    nsCOMPtr<nsIArray> typeArray;
+    rv = req->GetTypes(getter_AddRefs(typeArray));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsAutoCString access;
-    rv = req->GetAccess(access);
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsTArray<PermissionRequest> permArray;
+    ConvertArrayToPermissionRequest(typeArray, permArray);
 
     nsCOMPtr<nsIPrincipal> principal;
     rv = req->GetPrincipal(getter_AddRefs(principal));
     NS_ENSURE_SUCCESS(rv, rv);
 
     req->AddRef();
     child->SendPContentPermissionRequestConstructor(req,
-                                                    type,
-                                                    access,
+                                                    permArray,
                                                     IPC::Principal(principal));
 
     req->Sendprompt();
     return NS_OK;
   }
 
   // for chrome process
   nsCOMPtr<nsIContentPermissionPrompt> prompt =