dom/media/MediaPermissionGonk.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "MediaManager.h"
michael@0 6 #include "MediaPermissionGonk.h"
michael@0 7
michael@0 8 #include "nsCOMPtr.h"
michael@0 9 #include "nsCxPusher.h"
michael@0 10 #include "nsIContentPermissionPrompt.h"
michael@0 11 #include "nsIDocument.h"
michael@0 12 #include "nsIDOMNavigatorUserMedia.h"
michael@0 13 #include "nsIStringEnumerator.h"
michael@0 14 #include "nsISupportsArray.h"
michael@0 15 #include "nsJSUtils.h"
michael@0 16 #include "nsPIDOMWindow.h"
michael@0 17 #include "nsTArray.h"
michael@0 18 #include "GetUserMediaRequest.h"
michael@0 19 #include "PCOMContentPermissionRequestChild.h"
michael@0 20 #include "mozilla/dom/PBrowserChild.h"
michael@0 21 #include "mozilla/dom/TabChild.h"
michael@0 22 #include "mozilla/dom/MediaStreamTrackBinding.h"
michael@0 23 #include "nsISupportsPrimitives.h"
michael@0 24 #include "nsServiceManagerUtils.h"
michael@0 25 #include "nsArrayUtils.h"
michael@0 26 #include "nsContentPermissionHelper.h"
michael@0 27 #include "mozilla/dom/PermissionMessageUtils.h"
michael@0 28
michael@0 29 #define AUDIO_PERMISSION_NAME "audio-capture"
michael@0 30 #define VIDEO_PERMISSION_NAME "video-capture"
michael@0 31
michael@0 32 using namespace mozilla::dom;
michael@0 33
michael@0 34 namespace mozilla {
michael@0 35
michael@0 36 static MediaPermissionManager *gMediaPermMgr = nullptr;
michael@0 37
michael@0 38 static uint32_t
michael@0 39 ConvertArrayToPermissionRequest(nsIArray* aSrcArray,
michael@0 40 nsTArray<PermissionRequest>& aDesArray)
michael@0 41 {
michael@0 42 uint32_t len = 0;
michael@0 43 aSrcArray->GetLength(&len);
michael@0 44 for (uint32_t i = 0; i < len; i++) {
michael@0 45 nsCOMPtr<nsIContentPermissionType> cpt = do_QueryElementAt(aSrcArray, i);
michael@0 46 nsAutoCString type;
michael@0 47 nsAutoCString access;
michael@0 48 cpt->GetType(type);
michael@0 49 cpt->GetAccess(access);
michael@0 50
michael@0 51 nsCOMPtr<nsIArray> optionArray;
michael@0 52 cpt->GetOptions(getter_AddRefs(optionArray));
michael@0 53 uint32_t optionsLength = 0;
michael@0 54 optionArray->GetLength(&optionsLength);
michael@0 55 nsTArray<nsString> options;
michael@0 56 for (uint32_t j = 0; j < optionsLength; ++j) {
michael@0 57 nsCOMPtr<nsISupportsString> isupportsString = do_QueryElementAt(optionArray, j);
michael@0 58 if (isupportsString) {
michael@0 59 nsString option;
michael@0 60 isupportsString->GetData(option);
michael@0 61 options.AppendElement(option);
michael@0 62 }
michael@0 63 }
michael@0 64
michael@0 65 aDesArray.AppendElement(PermissionRequest(type, access, options));
michael@0 66 }
michael@0 67 return len;
michael@0 68 }
michael@0 69
michael@0 70 static void
michael@0 71 CreateDeviceNameList(nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices,
michael@0 72 nsTArray<nsString> &aDeviceNameList)
michael@0 73 {
michael@0 74 for (uint32_t i = 0; i < aDevices.Length(); ++i) {
michael@0 75 nsString name;
michael@0 76 nsresult rv = aDevices[i]->GetName(name);
michael@0 77 NS_ENSURE_SUCCESS_VOID(rv);
michael@0 78 aDeviceNameList.AppendElement(name);
michael@0 79 }
michael@0 80 }
michael@0 81
michael@0 82 static already_AddRefed<nsIMediaDevice>
michael@0 83 FindDeviceByName(nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices,
michael@0 84 const nsAString &aDeviceName)
michael@0 85 {
michael@0 86 for (uint32_t i = 0; i < aDevices.Length(); ++i) {
michael@0 87 nsCOMPtr<nsIMediaDevice> device = aDevices[i];
michael@0 88 nsString deviceName;
michael@0 89 device->GetName(deviceName);
michael@0 90 if (deviceName.Equals(aDeviceName)) {
michael@0 91 return device.forget();
michael@0 92 }
michael@0 93 }
michael@0 94
michael@0 95 return nullptr;
michael@0 96 }
michael@0 97
michael@0 98 // Helper function for notifying permission granted
michael@0 99 static nsresult
michael@0 100 NotifyPermissionAllow(const nsAString &aCallID, nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
michael@0 101 {
michael@0 102 nsresult rv;
michael@0 103 nsCOMPtr<nsISupportsArray> array;
michael@0 104 rv = NS_NewISupportsArray(getter_AddRefs(array));
michael@0 105 NS_ENSURE_SUCCESS(rv, rv);
michael@0 106
michael@0 107 for (uint32_t i = 0; i < aDevices.Length(); ++i) {
michael@0 108 rv = array->AppendElement(aDevices.ElementAt(i));
michael@0 109 NS_ENSURE_SUCCESS(rv, rv);
michael@0 110 }
michael@0 111
michael@0 112 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
michael@0 113 NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
michael@0 114
michael@0 115 return obs->NotifyObservers(array, "getUserMedia:response:allow",
michael@0 116 aCallID.BeginReading());
michael@0 117 }
michael@0 118
michael@0 119 // Helper function for notifying permision denial or error
michael@0 120 static nsresult
michael@0 121 NotifyPermissionDeny(const nsAString &aCallID, const nsAString &aErrorMsg)
michael@0 122 {
michael@0 123 nsresult rv;
michael@0 124 nsCOMPtr<nsISupportsString> supportsString =
michael@0 125 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
michael@0 126 NS_ENSURE_SUCCESS(rv, rv);
michael@0 127
michael@0 128 rv = supportsString->SetData(aErrorMsg);
michael@0 129 NS_ENSURE_SUCCESS(rv, rv);
michael@0 130
michael@0 131 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
michael@0 132 NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
michael@0 133
michael@0 134 return obs->NotifyObservers(supportsString, "getUserMedia:response:deny",
michael@0 135 aCallID.BeginReading());
michael@0 136 }
michael@0 137
michael@0 138 namespace {
michael@0 139
michael@0 140 /**
michael@0 141 * MediaPermissionRequest will send a prompt ipdl request to b2g process according
michael@0 142 * to its owned type.
michael@0 143 */
michael@0 144 class MediaPermissionRequest : public nsIContentPermissionRequest
michael@0 145 , public PCOMContentPermissionRequestChild
michael@0 146 {
michael@0 147 public:
michael@0 148 NS_DECL_ISUPPORTS
michael@0 149 NS_DECL_NSICONTENTPERMISSIONREQUEST
michael@0 150
michael@0 151 MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest> &aRequest,
michael@0 152 nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices);
michael@0 153 virtual ~MediaPermissionRequest() {}
michael@0 154
michael@0 155 // It will be called when prompt dismissed.
michael@0 156 virtual bool Recv__delete__(const bool &allow,
michael@0 157 const InfallibleTArray<PermissionChoice>& choices) MOZ_OVERRIDE;
michael@0 158 virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
michael@0 159
michael@0 160 already_AddRefed<nsPIDOMWindow> GetOwner();
michael@0 161
michael@0 162 private:
michael@0 163 nsresult DoAllow(const nsString &audioDevice, const nsString &videoDevice);
michael@0 164
michael@0 165 bool mAudio; // Request for audio permission
michael@0 166 bool mVideo; // Request for video permission
michael@0 167 nsRefPtr<dom::GetUserMediaRequest> mRequest;
michael@0 168 nsTArray<nsCOMPtr<nsIMediaDevice> > mAudioDevices; // candidate audio devices
michael@0 169 nsTArray<nsCOMPtr<nsIMediaDevice> > mVideoDevices; // candidate video devices
michael@0 170 };
michael@0 171
michael@0 172 // MediaPermissionRequest
michael@0 173 NS_IMPL_ISUPPORTS(MediaPermissionRequest, nsIContentPermissionRequest)
michael@0 174
michael@0 175 MediaPermissionRequest::MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest> &aRequest,
michael@0 176 nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
michael@0 177 : mRequest(aRequest)
michael@0 178 {
michael@0 179 dom::MediaStreamConstraints constraints;
michael@0 180 mRequest->GetConstraints(constraints);
michael@0 181
michael@0 182 mAudio = !constraints.mAudio.IsBoolean() || constraints.mAudio.GetAsBoolean();
michael@0 183 mVideo = !constraints.mVideo.IsBoolean() || constraints.mVideo.GetAsBoolean();
michael@0 184
michael@0 185 for (uint32_t i = 0; i < aDevices.Length(); ++i) {
michael@0 186 nsCOMPtr<nsIMediaDevice> device(aDevices[i]);
michael@0 187 nsAutoString deviceType;
michael@0 188 device->GetType(deviceType);
michael@0 189 if (mAudio && deviceType.EqualsLiteral("audio")) {
michael@0 190 mAudioDevices.AppendElement(device);
michael@0 191 }
michael@0 192 if (mVideo && deviceType.EqualsLiteral("video")) {
michael@0 193 mVideoDevices.AppendElement(device);
michael@0 194 }
michael@0 195 }
michael@0 196 }
michael@0 197
michael@0 198 // nsIContentPermissionRequest methods
michael@0 199 NS_IMETHODIMP
michael@0 200 MediaPermissionRequest::GetTypes(nsIArray** aTypes)
michael@0 201 {
michael@0 202 nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
michael@0 203 //XXX append device list
michael@0 204 if (mAudio) {
michael@0 205 nsTArray<nsString> audioDeviceNames;
michael@0 206 CreateDeviceNameList(mAudioDevices, audioDeviceNames);
michael@0 207 nsCOMPtr<nsISupports> AudioType =
michael@0 208 new ContentPermissionType(NS_LITERAL_CSTRING(AUDIO_PERMISSION_NAME),
michael@0 209 NS_LITERAL_CSTRING("unused"),
michael@0 210 audioDeviceNames);
michael@0 211 types->AppendElement(AudioType, false);
michael@0 212 }
michael@0 213 if (mVideo) {
michael@0 214 nsTArray<nsString> videoDeviceNames;
michael@0 215 CreateDeviceNameList(mVideoDevices, videoDeviceNames);
michael@0 216 nsCOMPtr<nsISupports> VideoType =
michael@0 217 new ContentPermissionType(NS_LITERAL_CSTRING(VIDEO_PERMISSION_NAME),
michael@0 218 NS_LITERAL_CSTRING("unused"),
michael@0 219 videoDeviceNames);
michael@0 220 types->AppendElement(VideoType, false);
michael@0 221 }
michael@0 222 NS_IF_ADDREF(*aTypes = types);
michael@0 223
michael@0 224 return NS_OK;
michael@0 225 }
michael@0 226
michael@0 227 NS_IMETHODIMP
michael@0 228 MediaPermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal)
michael@0 229 {
michael@0 230 NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
michael@0 231
michael@0 232 nsCOMPtr<nsPIDOMWindow> window = static_cast<nsPIDOMWindow*>
michael@0 233 (nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID()));
michael@0 234 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
michael@0 235
michael@0 236 nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
michael@0 237 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
michael@0 238
michael@0 239 NS_ADDREF(*aRequestingPrincipal = doc->NodePrincipal());
michael@0 240 return NS_OK;
michael@0 241 }
michael@0 242
michael@0 243 NS_IMETHODIMP
michael@0 244 MediaPermissionRequest::GetWindow(nsIDOMWindow** aRequestingWindow)
michael@0 245 {
michael@0 246 NS_ENSURE_ARG_POINTER(aRequestingWindow);
michael@0 247 nsCOMPtr<nsPIDOMWindow> window = static_cast<nsPIDOMWindow*>
michael@0 248 (nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID()));
michael@0 249 window.forget(aRequestingWindow);
michael@0 250 return NS_OK;
michael@0 251 }
michael@0 252
michael@0 253 NS_IMETHODIMP
michael@0 254 MediaPermissionRequest::GetElement(nsIDOMElement** aRequestingElement)
michael@0 255 {
michael@0 256 NS_ENSURE_ARG_POINTER(aRequestingElement);
michael@0 257 *aRequestingElement = nullptr;
michael@0 258 return NS_OK;
michael@0 259 }
michael@0 260
michael@0 261 NS_IMETHODIMP
michael@0 262 MediaPermissionRequest::Cancel()
michael@0 263 {
michael@0 264 nsString callID;
michael@0 265 mRequest->GetCallID(callID);
michael@0 266 NotifyPermissionDeny(callID, NS_LITERAL_STRING("Permission Denied"));
michael@0 267 return NS_OK;
michael@0 268 }
michael@0 269
michael@0 270 NS_IMETHODIMP
michael@0 271 MediaPermissionRequest::Allow(JS::HandleValue aChoices)
michael@0 272 {
michael@0 273 // check if JS object
michael@0 274 if (!aChoices.isObject()) {
michael@0 275 MOZ_ASSERT(false, "Not a correct format of PermissionChoice");
michael@0 276 return NS_ERROR_INVALID_ARG;
michael@0 277 }
michael@0 278 // iterate through audio-capture and video-capture
michael@0 279 AutoSafeJSContext cx;
michael@0 280 JS::Rooted<JSObject*> obj(cx, &aChoices.toObject());
michael@0 281 JSAutoCompartment ac(cx, obj);
michael@0 282 JS::Rooted<JS::Value> v(cx);
michael@0 283
michael@0 284 // get selected audio device name
michael@0 285 nsString audioDevice;
michael@0 286 if (mAudio) {
michael@0 287 if (!JS_GetProperty(cx, obj, AUDIO_PERMISSION_NAME, &v) || !v.isString()) {
michael@0 288 return NS_ERROR_FAILURE;
michael@0 289 }
michael@0 290 nsDependentJSString deviceName;
michael@0 291 if (!deviceName.init(cx, v)) {
michael@0 292 MOZ_ASSERT(false, "Couldn't initialize string from aChoices");
michael@0 293 return NS_ERROR_FAILURE;
michael@0 294 }
michael@0 295 audioDevice = deviceName;
michael@0 296 }
michael@0 297
michael@0 298 // get selected video device name
michael@0 299 nsString videoDevice;
michael@0 300 if (mVideo) {
michael@0 301 if (!JS_GetProperty(cx, obj, VIDEO_PERMISSION_NAME, &v) || !v.isString()) {
michael@0 302 return NS_ERROR_FAILURE;
michael@0 303 }
michael@0 304 nsDependentJSString deviceName;
michael@0 305 if (!deviceName.init(cx, v)) {
michael@0 306 MOZ_ASSERT(false, "Couldn't initialize string from aChoices");
michael@0 307 return NS_ERROR_FAILURE;
michael@0 308 }
michael@0 309 videoDevice = deviceName;
michael@0 310 }
michael@0 311
michael@0 312 return DoAllow(audioDevice, videoDevice);
michael@0 313 }
michael@0 314
michael@0 315 nsresult
michael@0 316 MediaPermissionRequest::DoAllow(const nsString &audioDevice,
michael@0 317 const nsString &videoDevice)
michael@0 318 {
michael@0 319 nsTArray<nsCOMPtr<nsIMediaDevice> > selectedDevices;
michael@0 320 if (mAudio) {
michael@0 321 nsCOMPtr<nsIMediaDevice> device =
michael@0 322 FindDeviceByName(mAudioDevices, audioDevice);
michael@0 323 if (device) {
michael@0 324 selectedDevices.AppendElement(device);
michael@0 325 }
michael@0 326 }
michael@0 327
michael@0 328 if (mVideo) {
michael@0 329 nsCOMPtr<nsIMediaDevice> device =
michael@0 330 FindDeviceByName(mVideoDevices, videoDevice);
michael@0 331 if (device) {
michael@0 332 selectedDevices.AppendElement(device);
michael@0 333 }
michael@0 334 }
michael@0 335
michael@0 336 nsString callID;
michael@0 337 mRequest->GetCallID(callID);
michael@0 338 return NotifyPermissionAllow(callID, selectedDevices);
michael@0 339 }
michael@0 340
michael@0 341 already_AddRefed<nsPIDOMWindow>
michael@0 342 MediaPermissionRequest::GetOwner()
michael@0 343 {
michael@0 344 nsCOMPtr<nsPIDOMWindow> window = static_cast<nsPIDOMWindow*>
michael@0 345 (nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID()));
michael@0 346 return window.forget();
michael@0 347 }
michael@0 348
michael@0 349 //PCOMContentPermissionRequestChild
michael@0 350 bool
michael@0 351 MediaPermissionRequest::Recv__delete__(const bool& allow,
michael@0 352 const InfallibleTArray<PermissionChoice>& choices)
michael@0 353 {
michael@0 354 if (allow) {
michael@0 355 // get selected device name for audio and video
michael@0 356 nsString audioDevice, videoDevice;
michael@0 357 for (uint32_t i = 0; i < choices.Length(); ++i) {
michael@0 358 const nsString &choice = choices[i].choice();
michael@0 359 if (choices[i].type().EqualsLiteral(AUDIO_PERMISSION_NAME)) {
michael@0 360 audioDevice = choice;
michael@0 361 } else if (choices[i].type().EqualsLiteral(VIDEO_PERMISSION_NAME)) {
michael@0 362 videoDevice = choice;
michael@0 363 }
michael@0 364 }
michael@0 365 (void) DoAllow(audioDevice, videoDevice);
michael@0 366 } else {
michael@0 367 (void) Cancel();
michael@0 368 }
michael@0 369 return true;
michael@0 370 }
michael@0 371
michael@0 372 // Success callback for MediaManager::GetUserMediaDevices().
michael@0 373 class MediaDeviceSuccessCallback: public nsIGetUserMediaDevicesSuccessCallback
michael@0 374 {
michael@0 375 public:
michael@0 376 NS_DECL_ISUPPORTS
michael@0 377 NS_DECL_NSIGETUSERMEDIADEVICESSUCCESSCALLBACK
michael@0 378
michael@0 379 MediaDeviceSuccessCallback(nsRefPtr<dom::GetUserMediaRequest> &aRequest)
michael@0 380 : mRequest(aRequest) {}
michael@0 381 virtual ~MediaDeviceSuccessCallback() {}
michael@0 382
michael@0 383 private:
michael@0 384 nsresult DoPrompt(nsRefPtr<MediaPermissionRequest> &req);
michael@0 385 nsRefPtr<dom::GetUserMediaRequest> mRequest;
michael@0 386 };
michael@0 387
michael@0 388 NS_IMPL_ISUPPORTS(MediaDeviceSuccessCallback, nsIGetUserMediaDevicesSuccessCallback)
michael@0 389
michael@0 390 // nsIGetUserMediaDevicesSuccessCallback method
michael@0 391 NS_IMETHODIMP
michael@0 392 MediaDeviceSuccessCallback::OnSuccess(nsIVariant* aDevices)
michael@0 393 {
michael@0 394 nsIID elementIID;
michael@0 395 uint16_t elementType;
michael@0 396 void* rawArray;
michael@0 397 uint32_t arrayLen;
michael@0 398
michael@0 399 nsresult rv;
michael@0 400 rv = aDevices->GetAsArray(&elementType, &elementIID, &arrayLen, &rawArray);
michael@0 401 NS_ENSURE_SUCCESS(rv, rv);
michael@0 402
michael@0 403 if (elementType != nsIDataType::VTYPE_INTERFACE) {
michael@0 404 NS_Free(rawArray);
michael@0 405 return NS_ERROR_FAILURE;
michael@0 406 }
michael@0 407
michael@0 408 // Create array for nsIMediaDevice
michael@0 409 nsTArray<nsCOMPtr<nsIMediaDevice> > devices;
michael@0 410
michael@0 411 nsISupports **supportsArray = reinterpret_cast<nsISupports **>(rawArray);
michael@0 412 for (uint32_t i = 0; i < arrayLen; ++i) {
michael@0 413 nsCOMPtr<nsIMediaDevice> device(do_QueryInterface(supportsArray[i]));
michael@0 414 devices.AppendElement(device);
michael@0 415 NS_IF_RELEASE(supportsArray[i]); // explicitly decrease reference count for raw pointer
michael@0 416 }
michael@0 417 NS_Free(rawArray); // explicitly free for the memory from nsIVariant::GetAsArray
michael@0 418
michael@0 419 // Send MediaPermissionRequest
michael@0 420 nsRefPtr<MediaPermissionRequest> req = new MediaPermissionRequest(mRequest, devices);
michael@0 421 rv = DoPrompt(req);
michael@0 422
michael@0 423 NS_ENSURE_SUCCESS(rv, rv);
michael@0 424 return NS_OK;
michael@0 425 }
michael@0 426
michael@0 427 // Trigger permission prompt UI
michael@0 428 nsresult
michael@0 429 MediaDeviceSuccessCallback::DoPrompt(nsRefPtr<MediaPermissionRequest> &req)
michael@0 430 {
michael@0 431 // for content process
michael@0 432 if (XRE_GetProcessType() == GeckoProcessType_Content) {
michael@0 433 MOZ_ASSERT(NS_IsMainThread()); // IPC can only be execute on main thread.
michael@0 434
michael@0 435 nsresult rv;
michael@0 436
michael@0 437 nsCOMPtr<nsPIDOMWindow> window(req->GetOwner());
michael@0 438 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
michael@0 439
michael@0 440 dom::TabChild* child = dom::TabChild::GetFrom(window->GetDocShell());
michael@0 441 NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
michael@0 442
michael@0 443 nsCOMPtr<nsIArray> typeArray;
michael@0 444 rv = req->GetTypes(getter_AddRefs(typeArray));
michael@0 445 NS_ENSURE_SUCCESS(rv, rv);
michael@0 446
michael@0 447 nsTArray<PermissionRequest> permArray;
michael@0 448 ConvertArrayToPermissionRequest(typeArray, permArray);
michael@0 449
michael@0 450 nsCOMPtr<nsIPrincipal> principal;
michael@0 451 rv = req->GetPrincipal(getter_AddRefs(principal));
michael@0 452 NS_ENSURE_SUCCESS(rv, rv);
michael@0 453
michael@0 454 req->AddRef();
michael@0 455 child->SendPContentPermissionRequestConstructor(req,
michael@0 456 permArray,
michael@0 457 IPC::Principal(principal));
michael@0 458
michael@0 459 req->Sendprompt();
michael@0 460 return NS_OK;
michael@0 461 }
michael@0 462
michael@0 463 // for chrome process
michael@0 464 nsCOMPtr<nsIContentPermissionPrompt> prompt =
michael@0 465 do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
michael@0 466 if (prompt) {
michael@0 467 prompt->Prompt(req);
michael@0 468 }
michael@0 469 return NS_OK;
michael@0 470 }
michael@0 471
michael@0 472 // Error callback for MediaManager::GetUserMediaDevices()
michael@0 473 class MediaDeviceErrorCallback: public nsIDOMGetUserMediaErrorCallback
michael@0 474 {
michael@0 475 public:
michael@0 476 NS_DECL_ISUPPORTS
michael@0 477 NS_DECL_NSIDOMGETUSERMEDIAERRORCALLBACK
michael@0 478
michael@0 479 MediaDeviceErrorCallback(const nsAString &aCallID)
michael@0 480 : mCallID(aCallID) {}
michael@0 481
michael@0 482 virtual ~MediaDeviceErrorCallback() {}
michael@0 483
michael@0 484 private:
michael@0 485 const nsString mCallID;
michael@0 486 };
michael@0 487
michael@0 488 NS_IMPL_ISUPPORTS(MediaDeviceErrorCallback, nsIDOMGetUserMediaErrorCallback)
michael@0 489
michael@0 490 // nsIDOMGetUserMediaErrorCallback method
michael@0 491 NS_IMETHODIMP
michael@0 492 MediaDeviceErrorCallback::OnError(const nsAString &aError)
michael@0 493 {
michael@0 494 return NotifyPermissionDeny(mCallID, aError);
michael@0 495 }
michael@0 496
michael@0 497 } // namespace anonymous
michael@0 498
michael@0 499 // MediaPermissionManager
michael@0 500 NS_IMPL_ISUPPORTS(MediaPermissionManager, nsIObserver)
michael@0 501
michael@0 502 MediaPermissionManager*
michael@0 503 MediaPermissionManager::GetInstance()
michael@0 504 {
michael@0 505 if (!gMediaPermMgr) {
michael@0 506 gMediaPermMgr = new MediaPermissionManager();
michael@0 507 }
michael@0 508
michael@0 509 return gMediaPermMgr;
michael@0 510 }
michael@0 511
michael@0 512 MediaPermissionManager::MediaPermissionManager()
michael@0 513 {
michael@0 514 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
michael@0 515 if (obs) {
michael@0 516 obs->AddObserver(this, "getUserMedia:request", false);
michael@0 517 obs->AddObserver(this, "xpcom-shutdown", false);
michael@0 518 }
michael@0 519 }
michael@0 520
michael@0 521 MediaPermissionManager::~MediaPermissionManager()
michael@0 522 {
michael@0 523 this->Deinit();
michael@0 524 }
michael@0 525
michael@0 526 nsresult
michael@0 527 MediaPermissionManager::Deinit()
michael@0 528 {
michael@0 529 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
michael@0 530 if (obs) {
michael@0 531 obs->RemoveObserver(this, "getUserMedia:request");
michael@0 532 obs->RemoveObserver(this, "xpcom-shutdown");
michael@0 533 }
michael@0 534 return NS_OK;
michael@0 535 }
michael@0 536
michael@0 537 // nsIObserver method
michael@0 538 NS_IMETHODIMP
michael@0 539 MediaPermissionManager::Observe(nsISupports* aSubject, const char* aTopic,
michael@0 540 const char16_t* aData)
michael@0 541 {
michael@0 542 nsresult rv;
michael@0 543 if (!strcmp(aTopic, "getUserMedia:request")) {
michael@0 544 nsRefPtr<dom::GetUserMediaRequest> req =
michael@0 545 static_cast<dom::GetUserMediaRequest*>(aSubject);
michael@0 546 rv = HandleRequest(req);
michael@0 547
michael@0 548 if (NS_FAILED(rv)) {
michael@0 549 nsString callID;
michael@0 550 req->GetCallID(callID);
michael@0 551 NotifyPermissionDeny(callID, NS_LITERAL_STRING("unable to enumerate media device"));
michael@0 552 }
michael@0 553 } else if (!strcmp(aTopic, "xpcom-shutdown")) {
michael@0 554 rv = this->Deinit();
michael@0 555 } else {
michael@0 556 // not reachable
michael@0 557 rv = NS_ERROR_FAILURE;
michael@0 558 }
michael@0 559 return rv;
michael@0 560 }
michael@0 561
michael@0 562 // Handle GetUserMediaRequest, query available media device first.
michael@0 563 nsresult
michael@0 564 MediaPermissionManager::HandleRequest(nsRefPtr<dom::GetUserMediaRequest> &req)
michael@0 565 {
michael@0 566 nsString callID;
michael@0 567 req->GetCallID(callID);
michael@0 568
michael@0 569 nsCOMPtr<nsPIDOMWindow> innerWindow = static_cast<nsPIDOMWindow*>
michael@0 570 (nsGlobalWindow::GetInnerWindowWithId(req->InnerWindowID()));
michael@0 571 if (!innerWindow) {
michael@0 572 MOZ_ASSERT(false, "No inner window");
michael@0 573 return NS_ERROR_FAILURE;
michael@0 574 }
michael@0 575
michael@0 576 nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess =
michael@0 577 new MediaDeviceSuccessCallback(req);
michael@0 578 nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError =
michael@0 579 new MediaDeviceErrorCallback(callID);
michael@0 580
michael@0 581 dom::MediaStreamConstraints constraints;
michael@0 582 req->GetConstraints(constraints);
michael@0 583
michael@0 584 nsRefPtr<MediaManager> MediaMgr = MediaManager::GetInstance();
michael@0 585 nsresult rv = MediaMgr->GetUserMediaDevices(innerWindow, constraints, onSuccess, onError);
michael@0 586 NS_ENSURE_SUCCESS(rv, rv);
michael@0 587
michael@0 588 return NS_OK;
michael@0 589 }
michael@0 590
michael@0 591 } // namespace mozilla

mercurial