Bug 788829 - Call SetSizeConstraints even if a popup is not open. r=enndeakin
[gecko.git] / dom / camera / DOMCameraCapabilities.cpp
blob257f592160e281cfea766799bf9ccaa6164440c9
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/. */
5 #include <cstring>
6 #include <cstdlib>
7 #include "base/basictypes.h"
8 #include "nsDOMClassInfo.h"
9 #include "jsapi.h"
10 #include "DOMCameraControl.h"
11 #include "DOMCameraCapabilities.h"
12 #include "CameraCommon.h"
14 using namespace mozilla;
16 DOMCI_DATA(CameraCapabilities, nsICameraCapabilities)
18 NS_IMPL_CYCLE_COLLECTION_0(DOMCameraCapabilities)
20 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMCameraCapabilities)
21 NS_INTERFACE_MAP_ENTRY(nsISupports)
22 NS_INTERFACE_MAP_ENTRY(nsICameraCapabilities)
23 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraCapabilities)
24 NS_INTERFACE_MAP_END
26 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMCameraCapabilities)
27 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMCameraCapabilities)
29 static nsresult
30 ParseZoomRatioItemAndAdd(JSContext* aCx, JSObject* aArray, uint32_t aIndex, const char* aStart, char** aEnd)
32 if (!*aEnd) {
33 // make 'aEnd' follow the same semantics as strchr().
34 aEnd = nullptr;
37 /**
38 * The by-100 divisor is Gonk-specific. For now, assume other platforms
39 * return actual fractoinal multipliers.
41 double d = strtod(aStart, aEnd);
42 #if MOZ_WIDGET_GONK
43 d /= 100;
44 #endif
46 jsval v = JS_NumberValue(d);
48 if (!JS_SetElement(aCx, aArray, aIndex, &v)) {
49 return NS_ERROR_FAILURE;
52 return NS_OK;
55 static nsresult
56 ParseStringItemAndAdd(JSContext* aCx, JSObject* aArray, uint32_t aIndex, const char* aStart, char** aEnd)
58 JSString* s;
60 if (*aEnd) {
61 s = JS_NewStringCopyN(aCx, aStart, *aEnd - aStart);
62 } else {
63 s = JS_NewStringCopyZ(aCx, aStart);
65 if (!s) {
66 return NS_ERROR_OUT_OF_MEMORY;
69 jsval v = STRING_TO_JSVAL(s);
70 if (!JS_SetElement(aCx, aArray, aIndex, &v)) {
71 return NS_ERROR_FAILURE;
74 return NS_OK;
77 static nsresult
78 ParseDimensionItemAndAdd(JSContext* aCx, JSObject* aArray, uint32_t aIndex, const char* aStart, char** aEnd)
80 char* x;
82 if (!*aEnd) {
83 // make 'aEnd' follow the same semantics as strchr().
84 aEnd = nullptr;
87 jsval w = INT_TO_JSVAL(strtol(aStart, &x, 10));
88 jsval h = INT_TO_JSVAL(strtol(x + 1, aEnd, 10));
90 JSObject* o = JS_NewObject(aCx, nullptr, nullptr, nullptr);
91 if (!o) {
92 return NS_ERROR_OUT_OF_MEMORY;
95 if (!JS_SetProperty(aCx, o, "width", &w)) {
96 return NS_ERROR_FAILURE;
98 if (!JS_SetProperty(aCx, o, "height", &h)) {
99 return NS_ERROR_FAILURE;
102 jsval v = OBJECT_TO_JSVAL(o);
103 if (!JS_SetElement(aCx, aArray, aIndex, &v)) {
104 return NS_ERROR_FAILURE;
107 return NS_OK;
110 nsresult
111 DOMCameraCapabilities::ParameterListToNewArray(JSContext* aCx, JSObject** aArray, uint32_t aKey, ParseItemAndAddFunc aParseItemAndAdd)
113 NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
115 const char* value = mCamera->GetParameterConstChar(aKey);
116 if (!value) {
117 // in case we get nonsense data back
118 *aArray = nullptr;
119 return NS_OK;
122 *aArray = JS_NewArrayObject(aCx, 0, nullptr);
123 if (!*aArray) {
124 return NS_ERROR_OUT_OF_MEMORY;
127 const char* p = value;
128 uint32_t index = 0;
129 nsresult rv;
130 char* q;
132 while (p) {
134 * In C's string.h, strchr() is declared as returning 'char*'; in C++'s
135 * cstring, it is declared as returning 'const char*', _except_ in MSVC,
136 * where the C version is declared to return const like the C++ version.
138 * Unfortunately, for both cases, strtod() and strtol() take a 'char**' as
139 * the end-of-conversion pointer, so we need to cast away strchr()'s
140 * const-ness here to make the MSVC build everything happy.
142 q = const_cast<char*>(strchr(p, ','));
143 if (q != p) { // skip consecutive delimiters, just in case
144 rv = aParseItemAndAdd(aCx, *aArray, index, p, &q);
145 NS_ENSURE_SUCCESS(rv, rv);
146 ++index;
148 p = q;
149 if (p) {
150 ++p;
154 return JS_FreezeObject(aCx, *aArray) ? NS_OK : NS_ERROR_FAILURE;
157 nsresult
158 DOMCameraCapabilities::StringListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey)
160 JSObject* array;
162 nsresult rv = ParameterListToNewArray(aCx, &array, aKey, ParseStringItemAndAdd);
163 NS_ENSURE_SUCCESS(rv, rv);
165 *aArray = OBJECT_TO_JSVAL(array);
166 return NS_OK;
169 nsresult
170 DOMCameraCapabilities::DimensionListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey)
172 JSObject* array;
173 nsresult rv;
175 rv = ParameterListToNewArray(aCx, &array, aKey, ParseDimensionItemAndAdd);
176 NS_ENSURE_SUCCESS(rv, rv);
178 *aArray = OBJECT_TO_JSVAL(array);
179 return NS_OK;
182 /* readonly attribute jsval previewSizes; */
183 NS_IMETHODIMP
184 DOMCameraCapabilities::GetPreviewSizes(JSContext* cx, JS::Value* aPreviewSizes)
186 return DimensionListToNewObject(cx, aPreviewSizes, CAMERA_PARAM_SUPPORTED_PREVIEWSIZES);
189 /* readonly attribute jsval pictureSizes; */
190 NS_IMETHODIMP
191 DOMCameraCapabilities::GetPictureSizes(JSContext* cx, JS::Value* aPictureSizes)
193 return DimensionListToNewObject(cx, aPictureSizes, CAMERA_PARAM_SUPPORTED_PICTURESIZES);
196 /* readonly attribute jsval fileFormats; */
197 NS_IMETHODIMP
198 DOMCameraCapabilities::GetFileFormats(JSContext* cx, JS::Value* aFileFormats)
200 return StringListToNewObject(cx, aFileFormats, CAMERA_PARAM_SUPPORTED_PICTUREFORMATS);
203 /* readonly attribute jsval whiteBalanceModes; */
204 NS_IMETHODIMP
205 DOMCameraCapabilities::GetWhiteBalanceModes(JSContext* cx, JS::Value* aWhiteBalanceModes)
207 return StringListToNewObject(cx, aWhiteBalanceModes, CAMERA_PARAM_SUPPORTED_WHITEBALANCES);
210 /* readonly attribute jsval sceneModes; */
211 NS_IMETHODIMP
212 DOMCameraCapabilities::GetSceneModes(JSContext* cx, JS::Value* aSceneModes)
214 return StringListToNewObject(cx, aSceneModes, CAMERA_PARAM_SUPPORTED_SCENEMODES);
217 /* readonly attribute jsval effects; */
218 NS_IMETHODIMP
219 DOMCameraCapabilities::GetEffects(JSContext* cx, JS::Value* aEffects)
221 return StringListToNewObject(cx, aEffects, CAMERA_PARAM_SUPPORTED_EFFECTS);
224 /* readonly attribute jsval flashModes; */
225 NS_IMETHODIMP
226 DOMCameraCapabilities::GetFlashModes(JSContext* cx, JS::Value* aFlashModes)
228 return StringListToNewObject(cx, aFlashModes, CAMERA_PARAM_SUPPORTED_FLASHMODES);
231 /* readonly attribute jsval focusModes; */
232 NS_IMETHODIMP
233 DOMCameraCapabilities::GetFocusModes(JSContext* cx, JS::Value* aFocusModes)
235 return StringListToNewObject(cx, aFocusModes, CAMERA_PARAM_SUPPORTED_FOCUSMODES);
238 /* readonly attribute long maxFocusAreas; */
239 NS_IMETHODIMP
240 DOMCameraCapabilities::GetMaxFocusAreas(JSContext* cx, int32_t* aMaxFocusAreas)
242 NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
244 const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS);
245 if (!value) {
246 // in case we get nonsense data back
247 *aMaxFocusAreas = 0;
248 return NS_OK;
251 *aMaxFocusAreas = atoi(value);
252 return NS_OK;
255 /* readonly attribute double minExposureCompensation; */
256 NS_IMETHODIMP
257 DOMCameraCapabilities::GetMinExposureCompensation(JSContext* cx, double* aMinExposureCompensation)
259 NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
261 const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION);
262 if (!value) {
263 // in case we get nonsense data back
264 *aMinExposureCompensation = 0;
265 return NS_OK;
268 *aMinExposureCompensation = atof(value);
269 return NS_OK;
272 /* readonly attribute double maxExposureCompensation; */
273 NS_IMETHODIMP
274 DOMCameraCapabilities::GetMaxExposureCompensation(JSContext* cx, double* aMaxExposureCompensation)
276 NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
278 const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION);
279 if (!value) {
280 // in case we get nonsense data back
281 *aMaxExposureCompensation = 0;
282 return NS_OK;
285 *aMaxExposureCompensation = atof(value);
286 return NS_OK;
289 /* readonly attribute double stepExposureCompensation; */
290 NS_IMETHODIMP
291 DOMCameraCapabilities::GetStepExposureCompensation(JSContext* cx, double* aStepExposureCompensation)
293 NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
295 const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP);
296 if (!value) {
297 // in case we get nonsense data back
298 *aStepExposureCompensation = 0;
299 return NS_OK;
302 *aStepExposureCompensation = atof(value);
303 return NS_OK;
306 /* readonly attribute long maxMeteringAreas; */
307 NS_IMETHODIMP
308 DOMCameraCapabilities::GetMaxMeteringAreas(JSContext* cx, int32_t* aMaxMeteringAreas)
310 NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
312 const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS);
313 if (!value) {
314 // in case we get nonsense data back
315 *aMaxMeteringAreas = 0;
316 return NS_OK;
319 *aMaxMeteringAreas = atoi(value);
320 return NS_OK;
323 /* readonly attribute jsval zoomRatios; */
324 NS_IMETHODIMP
325 DOMCameraCapabilities::GetZoomRatios(JSContext* cx, JS::Value* aZoomRatios)
327 NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
329 const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_ZOOM);
330 if (!value || strcmp(value, "true") != 0) {
331 // if zoom is not supported, return a null object
332 *aZoomRatios = JSVAL_NULL;
333 return NS_OK;
336 JSObject* array;
338 nsresult rv = ParameterListToNewArray(cx, &array, CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, ParseZoomRatioItemAndAdd);
339 NS_ENSURE_SUCCESS(rv, rv);
341 *aZoomRatios = OBJECT_TO_JSVAL(array);
342 return NS_OK;
345 /* readonly attribute jsval videoSizes; */
346 NS_IMETHODIMP
347 DOMCameraCapabilities::GetVideoSizes(JSContext* cx, JS::Value* aVideoSizes)
349 return DimensionListToNewObject(cx, aVideoSizes, CAMERA_PARAM_SUPPORTED_VIDEOSIZES);