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/. */
6 #include "nsPIDOMWindow.h"
7 #include "mozilla/Services.h"
8 #include "nsObserverService.h"
9 #include "nsIPermissionManager.h"
10 #include "DOMCameraControl.h"
11 #include "DOMCameraManager.h"
12 #include "nsDOMClassInfo.h"
13 #include "DictionaryHelpers.h"
14 #include "CameraCommon.h"
16 using namespace mozilla
;
19 DOMCI_DATA(CameraManager
, nsIDOMCameraManager
)
21 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMCameraManager
)
23 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMCameraManager
)
24 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCameraThread
)
25 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
27 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMCameraManager
)
28 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCameraThread
)
29 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
31 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCameraManager
)
32 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIObserver
)
33 NS_INTERFACE_MAP_ENTRY(nsIDOMCameraManager
)
34 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
35 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraManager
)
38 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCameraManager
)
39 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCameraManager
)
42 * Global camera logging object
44 * Set the NSPR_LOG_MODULES environment variable to enable logging
45 * in a debug build, e.g. NSPR_LOG_MODULES=Camera:5
50 static PRLogModuleInfo
*sLog
;
52 sLog
= PR_NewLogModule("Camera");
57 * nsDOMCameraManager::GetListOfCameras
58 * is implementation-specific, and can be found in (e.g.)
59 * GonkCameraManager.cpp and FallbackCameraManager.cpp.
62 WindowTable
nsDOMCameraManager::sActiveWindows
;
63 bool nsDOMCameraManager::sActiveWindowsInitialized
= false;
65 nsDOMCameraManager::nsDOMCameraManager(uint64_t aWindowId
)
66 : mWindowId(aWindowId
)
67 , mCameraThread(nullptr)
69 /* member initializers and constructor code */
70 DOM_CAMERA_LOGT("%s:%d : this=%p, windowId=%llx\n", __func__
, __LINE__
, this, mWindowId
);
73 nsDOMCameraManager::~nsDOMCameraManager()
76 DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__
, __LINE__
, this);
77 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
78 obs
->RemoveObserver(this, "xpcom-shutdown");
82 already_AddRefed
<nsDOMCameraManager
>
83 nsDOMCameraManager::CheckPermissionAndCreateInstance(nsPIDOMWindow
* aWindow
)
85 nsCOMPtr
<nsIPermissionManager
> permMgr
=
86 do_GetService(NS_PERMISSIONMANAGER_CONTRACTID
);
87 NS_ENSURE_TRUE(permMgr
, nullptr);
89 uint32_t permission
= nsIPermissionManager::DENY_ACTION
;
90 permMgr
->TestPermissionFromWindow(aWindow
, "camera", &permission
);
91 if (permission
!= nsIPermissionManager::ALLOW_ACTION
) {
92 NS_WARNING("No permission to access camera");
96 // Initialize the shared active window tracker
97 if (!sActiveWindowsInitialized
) {
98 sActiveWindows
.Init();
99 sActiveWindowsInitialized
= true;
102 nsRefPtr
<nsDOMCameraManager
> cameraManager
=
103 new nsDOMCameraManager(aWindow
->WindowID());
105 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
106 obs
->AddObserver(cameraManager
, "xpcom-shutdown", true);
108 return cameraManager
.forget();
111 /* [implicit_jscontext] void getCamera ([optional] in jsval aOptions, in nsICameraGetCameraCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
113 nsDOMCameraManager::GetCamera(const JS::Value
& aOptions
, nsICameraGetCameraCallback
* onSuccess
, nsICameraErrorCallback
* onError
, JSContext
* cx
)
115 NS_ENSURE_TRUE(onSuccess
, NS_ERROR_INVALID_ARG
);
117 uint32_t cameraId
= 0; // back (or forward-facing) camera by default
118 CameraSelector selector
;
120 nsresult rv
= selector
.Init(cx
, &aOptions
);
121 NS_ENSURE_SUCCESS(rv
, rv
);
123 if (selector
.camera
.EqualsASCII("front")) {
127 // reuse the same camera thread to conserve resources
128 if (!mCameraThread
) {
129 rv
= NS_NewThread(getter_AddRefs(mCameraThread
));
130 NS_ENSURE_SUCCESS(rv
, rv
);
133 DOM_CAMERA_LOGT("%s:%d\n", __func__
, __LINE__
);
135 // Creating this object will trigger the onSuccess handler
136 nsCOMPtr
<nsDOMCameraControl
> cameraControl
= new nsDOMCameraControl(cameraId
, mCameraThread
, onSuccess
, onError
, mWindowId
);
138 Register(cameraControl
);
143 nsDOMCameraManager::Register(nsDOMCameraControl
* aDOMCameraControl
)
145 DOM_CAMERA_LOGI(">>> Register( aDOMCameraControl = %p ) mWindowId = 0x%llx\n", aDOMCameraControl
, mWindowId
);
146 MOZ_ASSERT(NS_IsMainThread());
148 // Put the camera control into the hash table
149 CameraControls
* controls
= sActiveWindows
.Get(mWindowId
);
151 controls
= new CameraControls
;
152 sActiveWindows
.Put(mWindowId
, controls
);
154 controls
->AppendElement(aDOMCameraControl
);
158 nsDOMCameraManager::Shutdown(uint64_t aWindowId
)
160 DOM_CAMERA_LOGI(">>> Shutdown( aWindowId = 0x%llx )\n", aWindowId
);
161 MOZ_ASSERT(NS_IsMainThread());
163 CameraControls
* controls
= sActiveWindows
.Get(aWindowId
);
168 uint32_t length
= controls
->Length();
169 for (uint32_t i
= 0; i
< length
; i
++) {
170 nsRefPtr
<nsDOMCameraControl
> cameraControl
= controls
->ElementAt(i
);
171 cameraControl
->Shutdown();
175 sActiveWindows
.Remove(aWindowId
);
179 nsDOMCameraManager::XpComShutdown()
181 DOM_CAMERA_LOGI(">>> XPCOM Shutdown\n");
182 MOZ_ASSERT(NS_IsMainThread());
184 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
185 obs
->RemoveObserver(this, "xpcom-shutdown");
187 sActiveWindows
.Clear();
191 nsDOMCameraManager::Observe(nsISupports
* aSubject
, const char* aTopic
, const PRUnichar
* aData
)
193 if (strcmp(aTopic
, "xpcom-shutdown") == 0) {
200 nsDOMCameraManager::OnNavigation(uint64_t aWindowId
)
202 DOM_CAMERA_LOGI(">>> OnNavigation event\n");
207 nsDOMCameraManager::IsWindowStillActive(uint64_t aWindowId
)
209 MOZ_ASSERT(NS_IsMainThread());
211 if (!sActiveWindowsInitialized
) {
215 return !!sActiveWindows
.Get(aWindowId
);