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_NSCOMPTR(mCameraThread
)
25 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
27 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMCameraManager
)
28 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(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
47 PRLogModuleInfo
* gCameraLog
= PR_LOG_DEFINE("Camera");
50 * nsDOMCameraManager::GetListOfCameras
51 * is implementation-specific, and can be found in (e.g.)
52 * GonkCameraManager.cpp and FallbackCameraManager.cpp.
55 WindowTable
nsDOMCameraManager::sActiveWindows
;
56 bool nsDOMCameraManager::sActiveWindowsInitialized
= false;
58 nsDOMCameraManager::nsDOMCameraManager(uint64_t aWindowId
)
59 : mWindowId(aWindowId
)
60 , mCameraThread(nullptr)
62 /* member initializers and constructor code */
63 DOM_CAMERA_LOGT("%s:%d : this=%p, windowId=%llx\n", __func__
, __LINE__
, this, mWindowId
);
66 nsDOMCameraManager::~nsDOMCameraManager()
69 DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__
, __LINE__
, this);
70 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
71 obs
->RemoveObserver(this, "xpcom-shutdown");
75 already_AddRefed
<nsDOMCameraManager
>
76 nsDOMCameraManager::CheckPermissionAndCreateInstance(nsPIDOMWindow
* aWindow
)
78 nsCOMPtr
<nsIPermissionManager
> permMgr
=
79 do_GetService(NS_PERMISSIONMANAGER_CONTRACTID
);
80 NS_ENSURE_TRUE(permMgr
, nullptr);
82 uint32_t permission
= nsIPermissionManager::DENY_ACTION
;
83 permMgr
->TestPermissionFromWindow(aWindow
, "camera", &permission
);
84 if (permission
!= nsIPermissionManager::ALLOW_ACTION
) {
85 NS_WARNING("No permission to access camera");
89 // Initialize the shared active window tracker
90 if (!sActiveWindowsInitialized
) {
91 sActiveWindows
.Init();
92 sActiveWindowsInitialized
= true;
95 nsRefPtr
<nsDOMCameraManager
> cameraManager
=
96 new nsDOMCameraManager(aWindow
->WindowID());
98 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
99 obs
->AddObserver(cameraManager
, "xpcom-shutdown", true);
101 return cameraManager
.forget();
104 /* [implicit_jscontext] void getCamera ([optional] in jsval aOptions, in nsICameraGetCameraCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
106 nsDOMCameraManager::GetCamera(const JS::Value
& aOptions
, nsICameraGetCameraCallback
* onSuccess
, nsICameraErrorCallback
* onError
, JSContext
* cx
)
108 NS_ENSURE_TRUE(onSuccess
, NS_ERROR_INVALID_ARG
);
110 uint32_t cameraId
= 0; // back (or forward-facing) camera by default
111 CameraSelector selector
;
113 nsresult rv
= selector
.Init(cx
, &aOptions
);
114 NS_ENSURE_SUCCESS(rv
, rv
);
116 if (selector
.camera
.EqualsASCII("front")) {
120 // reuse the same camera thread to conserve resources
121 if (!mCameraThread
) {
122 rv
= NS_NewThread(getter_AddRefs(mCameraThread
));
123 NS_ENSURE_SUCCESS(rv
, rv
);
126 DOM_CAMERA_LOGT("%s:%d\n", __func__
, __LINE__
);
128 // Creating this object will trigger the onSuccess handler
129 nsCOMPtr
<nsDOMCameraControl
> cameraControl
= new nsDOMCameraControl(cameraId
, mCameraThread
, onSuccess
, onError
, mWindowId
);
131 Register(cameraControl
);
136 nsDOMCameraManager::Register(nsDOMCameraControl
* aDOMCameraControl
)
138 DOM_CAMERA_LOGI(">>> Register( aDOMCameraControl = %p ) mWindowId = 0x%llx\n", aDOMCameraControl
, mWindowId
);
139 MOZ_ASSERT(NS_IsMainThread());
141 // Put the camera control into the hash table
142 CameraControls
* controls
= sActiveWindows
.Get(mWindowId
);
144 controls
= new CameraControls
;
145 sActiveWindows
.Put(mWindowId
, controls
);
147 controls
->AppendElement(aDOMCameraControl
);
151 nsDOMCameraManager::Shutdown(uint64_t aWindowId
)
153 DOM_CAMERA_LOGI(">>> Shutdown( aWindowId = 0x%llx )\n", aWindowId
);
154 MOZ_ASSERT(NS_IsMainThread());
156 CameraControls
* controls
= sActiveWindows
.Get(aWindowId
);
161 uint32_t length
= controls
->Length();
162 for (uint32_t i
= 0; i
< length
; i
++) {
163 nsRefPtr
<nsDOMCameraControl
> cameraControl
= controls
->ElementAt(i
);
164 cameraControl
->Shutdown();
168 sActiveWindows
.Remove(aWindowId
);
172 nsDOMCameraManager::XpComShutdown()
174 DOM_CAMERA_LOGI(">>> XPCOM Shutdown\n");
175 MOZ_ASSERT(NS_IsMainThread());
177 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
178 obs
->RemoveObserver(this, "xpcom-shutdown");
180 sActiveWindows
.Clear();
184 nsDOMCameraManager::Observe(nsISupports
* aSubject
, const char* aTopic
, const PRUnichar
* aData
)
186 if (strcmp(aTopic
, "xpcom-shutdown") == 0) {
193 nsDOMCameraManager::OnNavigation(uint64_t aWindowId
)
195 DOM_CAMERA_LOGI(">>> OnNavigation event\n");
200 nsDOMCameraManager::IsWindowStillActive(uint64_t aWindowId
)
202 MOZ_ASSERT(NS_IsMainThread());
204 if (!sActiveWindowsInitialized
) {
208 return !!sActiveWindows
.Get(aWindowId
);