Bug 1308114 - Setup camera engine when the script sets navigator.mediaDevices.ondevicechange; r=jesup
MozReview-Commit-ID: CCp3EQzHd1u
--- a/dom/media/systemservices/CamerasChild.cpp
+++ b/dom/media/systemservices/CamerasChild.cpp
@@ -141,16 +141,34 @@ GetCamerasChild() {
}
CamerasChild*
GetCamerasChildIfExists() {
OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
return CamerasSingleton::Child();
}
+int CamerasChild::AddDeviceChangeCallback(DeviceChangeCallback* aCallback)
+{
+ // According to the spec, if the script sets
+ // navigator.mediaDevices.ondevicechange and the permission state is
+ // "always granted", the User Agent MUST fires a devicechange event when
+ // a new media input device is made available, even the script never
+ // call getusermedia or enumerateDevices.
+
+ // In order to detect the event, we need to init the camera engine.
+ // Currently EnsureInitialized(aCapEngine) is only called when one of
+ // CamerasaParent api, e.g., RecvNumberOfCaptureDevices(), is called.
+
+ // So here we setup camera engine via EnsureInitialized(aCapEngine)
+
+ EnsureInitialized(CameraEngine);
+ return DeviceChangeCallback::AddDeviceChangeCallback(aCallback);
+}
+
bool
CamerasChild::RecvReplyFailure(void)
{
LOG((__PRETTY_FUNCTION__));
MonitorAutoLock monitor(mReplyMonitor);
mReceivedReply = true;
mReplySuccess = false;
monitor.Notify();
@@ -302,16 +320,32 @@ CamerasChild::RecvReplyNumberOfCaptureDe
mReceivedReply = true;
mReplySuccess = true;
mReplyInteger = numdev;
monitor.Notify();
return true;
}
int
+CamerasChild::EnsureInitialized(CaptureEngine aCapEngine)
+{
+ LOG((__PRETTY_FUNCTION__));
+ nsCOMPtr<nsIRunnable> runnable =
+ media::NewRunnableFrom([this, aCapEngine]() -> nsresult {
+ if (this->SendEnsureInitialized(aCapEngine)) {
+ return NS_OK;
+ }
+ return NS_ERROR_FAILURE;
+ });
+ LockAndDispatch<> dispatcher(this, __func__, runnable, 0, mReplyInteger);
+ LOG(("Capture Devices: %d", dispatcher.ReturnValue()));
+ return dispatcher.ReturnValue();
+}
+
+int
CamerasChild::GetCaptureCapability(CaptureEngine aCapEngine,
const char* unique_idUTF8,
const unsigned int capability_number,
webrtc::CaptureCapability& capability)
{
LOG(("GetCaptureCapability: %s %d", unique_idUTF8, capability_number));
nsCString unique_id(unique_idUTF8);
nsCOMPtr<nsIRunnable> runnable =
--- a/dom/media/systemservices/CamerasChild.h
+++ b/dom/media/systemservices/CamerasChild.h
@@ -151,16 +151,17 @@ public:
// these are the actual callbacks with data
virtual bool RecvDeliverFrame(const CaptureEngine&, const int&, mozilla::ipc::Shmem&&,
const size_t&, const uint32_t&, const int64_t&,
const int64_t&) override;
virtual bool RecvFrameSizeChange(const CaptureEngine&, const int&,
const int& w, const int& h) override;
virtual bool RecvDeviceChange() override;
+ virtual int AddDeviceChangeCallback(DeviceChangeCallback* aCallback) override;
int SetFakeDeviceChangeEvents();
// these are response messages to our outgoing requests
virtual bool RecvReplyNumberOfCaptureDevices(const int&) override;
virtual bool RecvReplyNumberOfCapabilities(const int&) override;
virtual bool RecvReplyAllocateCaptureDevice(const int&) override;
virtual bool RecvReplyGetCaptureCapability(const CaptureCapability& capability) override;
virtual bool RecvReplyGetCaptureDevice(const nsCString& device_name,
@@ -191,16 +192,17 @@ public:
const unsigned int capability_number,
webrtc::CaptureCapability& capability);
int GetCaptureDevice(CaptureEngine aCapEngine,
unsigned int list_number, char* device_nameUTF8,
const unsigned int device_nameUTF8Length,
char* unique_idUTF8,
const unsigned int unique_idUTF8Length);
void ShutdownAll();
+ int EnsureInitialized(CaptureEngine aCapEngine);
webrtc::ExternalRenderer* Callback(CaptureEngine aCapEngine, int capture_id);
private:
CamerasChild();
~CamerasChild();
// Dispatch a Runnable to the PCamerasParent, by executing it on the
// decidecated Cameras IPC/PBackground thread.
--- a/dom/media/systemservices/CamerasParent.cpp
+++ b/dom/media/systemservices/CamerasParent.cpp
@@ -542,16 +542,48 @@ CamerasParent::RecvNumberOfCaptureDevice
self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
return NS_OK;
});
DispatchToVideoCaptureThread(webrtc_runnable);
return true;
}
bool
+CamerasParent::RecvEnsureInitialized(const CaptureEngine& aCapEngine)
+{
+ LOG((__PRETTY_FUNCTION__));
+
+ RefPtr<CamerasParent> self(this);
+ RefPtr<Runnable> webrtc_runnable =
+ media::NewRunnableFrom([self, aCapEngine]() -> nsresult {
+ bool result = self->EnsureInitialized(aCapEngine);
+
+ RefPtr<nsIRunnable> ipc_runnable =
+ media::NewRunnableFrom([self, result]() -> nsresult {
+ if (self->IsShuttingDown()) {
+ return NS_ERROR_FAILURE;
+ }
+ if (!result) {
+ LOG(("RecvEnsureInitialized failed"));
+ Unused << self->SendReplyFailure();
+ return NS_ERROR_FAILURE;
+ } else {
+ LOG(("RecvEnsureInitialized succeeded"));
+ Unused << self->SendReplySuccess();
+ return NS_OK;
+ }
+ });
+ self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+ return NS_OK;
+ });
+ DispatchToVideoCaptureThread(webrtc_runnable);
+ return true;
+}
+
+bool
CamerasParent::RecvNumberOfCapabilities(const CaptureEngine& aCapEngine,
const nsCString& unique_id)
{
LOG((__PRETTY_FUNCTION__));
LOG(("Getting caps for %s", unique_id.get()));
RefPtr<CamerasParent> self(this);
RefPtr<Runnable> webrtc_runnable =
--- a/dom/media/systemservices/CamerasParent.h
+++ b/dom/media/systemservices/CamerasParent.h
@@ -110,16 +110,17 @@ public:
const int&) override;
virtual bool RecvGetCaptureDevice(const CaptureEngine&, const int&) override;
virtual bool RecvStartCapture(const CaptureEngine&, const int&,
const CaptureCapability&) override;
virtual bool RecvStopCapture(const CaptureEngine&, const int&) override;
virtual bool RecvReleaseFrame(mozilla::ipc::Shmem&&) override;
virtual bool RecvAllDone() override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+ virtual bool RecvEnsureInitialized(const CaptureEngine&) override;
nsIThread* GetBackgroundThread() { return mPBackgroundThread; };
bool IsShuttingDown() { return !mChildIsAlive
|| mDestroyed
|| !mWebRTCAlive; };
ShmemBuffer GetBuffer(size_t aSize);
// helper to forward to the PBackground thread
--- a/dom/media/systemservices/PCameras.ipdl
+++ b/dom/media/systemservices/PCameras.ipdl
@@ -52,12 +52,14 @@ parent:
async ReleaseCaptureDevice(CaptureEngine engine, int numdev);
async StartCapture(CaptureEngine engine, int numdev, CaptureCapability capability);
async StopCapture(CaptureEngine engine, int numdev);
// transfers frame back
async ReleaseFrame(Shmem s);
// Ask parent to delete us
async AllDone();
+ // setup camera engine
+ async EnsureInitialized(CaptureEngine engine);
};
} // namespace camera
} // namespace mozilla