1 /*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "picker/camera_picker_napi.h"
17
18 #include <algorithm>
19 #include <memory>
20 #include <mutex>
21 #include <new>
22 #include <vector>
23
24 #include "ability_lifecycle_callback.h"
25 #include "bool_wrapper.h"
26 #include "camera_device.h"
27 #include "camera_log.h"
28 #include "int_wrapper.h"
29 #include "js_native_api.h"
30 #include "napi/native_common.h"
31 #include "napi_base_context.h"
32 #include "string_wrapper.h"
33
34 namespace OHOS {
35 namespace CameraStandard {
36 namespace {
37 constexpr char CAMERA_PICKER_BUNDLE_HAP_NAME[] = "com.huawei.hmos.camera";
38 constexpr char CAMERA_PICKER_BUNDLE_ABILITY_NAME[] = "PickerAbility";
39 constexpr char CAMERA_PICKER_ABILITY_ACTION_PHOTO[] = "ohos.want.action.imageCapture";
40 constexpr char CAMERA_PICKER_ABILITY_ACTION_VIDEO[] = "ohos.want.action.videoCapture";
41 const std::map<std::string, PickerMediaType> PICKER_MEDIA_TYPE_MAP = {
42 { "photo", PickerMediaType::PHOTO },
43 { "video", PickerMediaType::VIDEO },
44 };
45 constexpr char CAMERA_PICKER_NAPI_CLASS_NAME[] = "CameraPicker";
46 const char* const PICKER_MEDIA_TYPE[] = { "PHOTO", "VIDEO" };
47 const std::vector<std::string> PICKER_MEDIA_TYPE_VALUE = { "photo", "video" };
48 } // namespace
49
50 using namespace std;
51 thread_local napi_ref CameraPickerNapi::sConstructor_ = nullptr;
52 thread_local napi_ref CameraPickerNapi::mediaTypeRef_ = nullptr;
53 thread_local uint32_t CameraPickerNapi::cameraPickerTaskId = CAMERA_PICKER_TASKID;
54
CameraPickerNapi()55 CameraPickerNapi::CameraPickerNapi() : env_(nullptr)
56 {
57 CAMERA_SYNC_TRACE;
58 }
59
~CameraPickerNapi()60 CameraPickerNapi::~CameraPickerNapi()
61 {
62 MEDIA_DEBUG_LOG("~CameraPickerNapi is called");
63 }
64
GetAbilityContext(napi_env env,napi_value value)65 static std::shared_ptr<PickerContextProxy> GetAbilityContext(napi_env env, napi_value value)
66 {
67 MEDIA_DEBUG_LOG("GetAbilityContext is called");
68 bool stageMode = false;
69 napi_status status = OHOS::AbilityRuntime::IsStageContext(env, value, stageMode);
70 if (status != napi_ok || !stageMode) {
71 MEDIA_ERR_LOG("GetAbilityContext It is not stage Mode");
72 return nullptr;
73 }
74 auto context = AbilityRuntime::GetStageModeContext(env, value);
75 if (context == nullptr) {
76 MEDIA_ERR_LOG("GetAbilityContext get context failed context");
77 return nullptr;
78 }
79 auto contextProxy = std::make_shared<PickerContextProxy>(context);
80 if (contextProxy == nullptr || contextProxy->GetType() == PickerContextType::UNKNOWN) {
81 MEDIA_ERR_LOG("GetAbilityContext AbilityRuntime convert context failed");
82 return nullptr;
83 }
84 if (contextProxy->GetType() == PickerContextType::UI_EXTENSION) {
85 MEDIA_INFO_LOG("GetAbilityContext type is UI_EXTENSION");
86 } else if (contextProxy->GetType() == PickerContextType::ABILITY) {
87 MEDIA_INFO_LOG("GetAbilityContext type is ABILITY");
88 } else {
89 // Do nothing.
90 }
91 MEDIA_DEBUG_LOG("CameraPickerNapi GetAbilityContext success");
92 return contextProxy;
93 }
94
GetMediaTypes(napi_env env,napi_value napiMediaTypesArray,std::vector<PickerMediaType> & mediaTypes)95 static bool GetMediaTypes(napi_env env, napi_value napiMediaTypesArray, std::vector<PickerMediaType>& mediaTypes)
96 {
97 MEDIA_DEBUG_LOG("GetMediaTypes is called");
98 uint32_t typeLen;
99 if (napi_get_array_length(env, napiMediaTypesArray, &typeLen) != napi_ok) {
100 MEDIA_ERR_LOG("napi_get_array_length failed");
101 return false;
102 }
103 for (uint32_t i = 0; i < typeLen; i++) {
104 napi_value element;
105 if (napi_get_element(env, napiMediaTypesArray, i, &element) != napi_ok) {
106 MEDIA_ERR_LOG("napi_get_element failed");
107 return false;
108 }
109 std::string typeString;
110 size_t stringSize = 0;
111 if (napi_get_value_string_utf8(env, element, nullptr, 0, &stringSize) != napi_ok) {
112 MEDIA_ERR_LOG("napi_get_value_string_utf8 failed");
113 return false;
114 }
115 typeString.reserve(stringSize + 1);
116 typeString.resize(stringSize);
117 if (napi_get_value_string_utf8(env, element, typeString.data(), (stringSize + 1), &stringSize) != napi_ok) {
118 MEDIA_ERR_LOG("napi_get_value_string_utf8 failed");
119 return false;
120 }
121 auto it = PICKER_MEDIA_TYPE_MAP.find(typeString.c_str());
122 if (it != PICKER_MEDIA_TYPE_MAP.end()) {
123 mediaTypes.emplace_back(it->second);
124 }
125 }
126 MEDIA_DEBUG_LOG("GetMediaTypes end valid size is %{public}zu", mediaTypes.size());
127 return true;
128 }
129
GetPickerProfile(napi_env env,napi_value napiPickerProfile,PickerProfile & pickerProfile)130 static bool GetPickerProfile(napi_env env, napi_value napiPickerProfile, PickerProfile& pickerProfile)
131 {
132 MEDIA_DEBUG_LOG("GetPickerProfile is called");
133 napi_value value = nullptr;
134
135 // get cameraPosition
136 if (napi_get_named_property(env, napiPickerProfile, "cameraPosition", &value) != napi_ok) {
137 MEDIA_ERR_LOG("napi_get_named_property failed");
138 return false;
139 }
140 int32_t cameraPosition = 0;
141 if (napi_get_value_int32(env, value, &cameraPosition) != napi_ok) {
142 MEDIA_WARNING_LOG("napi_get_value_int32 failed");
143 }
144 // get videoDuration
145 if (napi_get_named_property(env, napiPickerProfile, "videoDuration", &value) != napi_ok) {
146 MEDIA_ERR_LOG("napi_get_named_property failed");
147 return false;
148 }
149 int32_t videoDuration = 0;
150 if (napi_get_value_int32(env, value, &videoDuration) != napi_ok) {
151 MEDIA_WARNING_LOG("napi_get_value_int32 failed");
152 }
153 // get saveUri
154 char saveUri[PATH_MAX];
155 size_t length = 0;
156 if (napi_get_named_property(env, napiPickerProfile, "saveUri", &value) != napi_ok) {
157 MEDIA_ERR_LOG("napi_get_named_property failed");
158 return false;
159 }
160 if (napi_get_value_string_utf8(env, value, saveUri, PATH_MAX, &length) != napi_ok) {
161 MEDIA_WARNING_LOG("get saveUri fail!");
162 }
163 pickerProfile.cameraPosition = static_cast<CameraPosition>(cameraPosition);
164 pickerProfile.videoDuration = videoDuration;
165 pickerProfile.saveUri = std::string(saveUri);
166 MEDIA_INFO_LOG("GetPickerProfile cameraPosition: %{public}d, duration: %{public}d", cameraPosition, videoDuration);
167 MEDIA_INFO_LOG("GetPickerProfile saveUri: %{public}s", saveUri);
168 return true;
169 }
170
SetPickerWantParams(AAFwk::Want & want,std::shared_ptr<PickerContextProxy> & pickerContextProxy,const vector<PickerMediaType> & mediaTypes,PickerProfile & pickerProfile)171 static void SetPickerWantParams(AAFwk::Want& want, std::shared_ptr<PickerContextProxy>& pickerContextProxy,
172 const vector<PickerMediaType>& mediaTypes, PickerProfile& pickerProfile)
173 {
174 MEDIA_DEBUG_LOG("SetPickerWantParams enter");
175 AAFwk::WantParams wantParam;
176 bool isPhotoType = false;
177 bool isVideoType = false;
178 for (auto type : mediaTypes) {
179 MEDIA_INFO_LOG("SetPickerWantParams current type is:%{public}d", type);
180 switch (type) {
181 case PickerMediaType::PHOTO:
182 isPhotoType = true;
183 break;
184 case PickerMediaType::VIDEO:
185 isVideoType = true;
186 break;
187 }
188 }
189
190 want.SetElementName(CAMERA_PICKER_BUNDLE_HAP_NAME, CAMERA_PICKER_BUNDLE_ABILITY_NAME);
191 want.SetUri(pickerProfile.saveUri);
192 want.SetFlags(AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION | AAFwk::Want::FLAG_AUTH_WRITE_URI_PERMISSION);
193 wantParam.SetParam("ability.want.params.uiExtensionTargetType", AAFwk::String::Box("cameraPicker"));
194 wantParam.SetParam("callBundleName", AAFwk::String::Box(pickerContextProxy->GetBundleName().c_str()));
195 wantParam.SetParam("cameraPosition", AAFwk::Integer::Box(pickerProfile.cameraPosition));
196 wantParam.SetParam("videoDuration", AAFwk::Integer::Box(pickerProfile.videoDuration));
197 wantParam.SetParam("saveUri", AAFwk::String::Box(pickerProfile.saveUri.c_str()));
198 if (isPhotoType && isVideoType) {
199 wantParam.SetParam("supportMultiMode", AAFwk::Boolean::Box(true));
200 }
201 want.SetParams(wantParam);
202 if (isPhotoType) {
203 want.SetAction(CAMERA_PICKER_ABILITY_ACTION_PHOTO);
204 } else if (isVideoType) {
205 want.SetAction(CAMERA_PICKER_ABILITY_ACTION_VIDEO);
206 } else {
207 MEDIA_ERR_LOG("SetPickerWantParams set action fail!");
208 }
209 MEDIA_DEBUG_LOG("SetPickerWantParams end");
210 }
211
CommonCompleteCallback(napi_env env,napi_status status,void * data)212 static void CommonCompleteCallback(napi_env env, napi_status status, void* data)
213 {
214 MEDIA_INFO_LOG("CommonCompleteCallback is called");
215 napi_value callbackObj = nullptr;
216 napi_value resultCode = nullptr;
217 napi_value resultUri = nullptr;
218 napi_value resultMediaType = nullptr;
219 auto context = static_cast<CameraPickerAsyncContext*>(data);
220 if (context == nullptr) {
221 MEDIA_ERR_LOG("Async context is null");
222 return;
223 }
224
225 std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
226
227 if (!context->status) {
228 CameraNapiUtils::CreateNapiErrorObject(env, context->errorCode, context->errorMsg.c_str(), jsContext);
229 } else {
230 jsContext->status = true;
231 napi_get_undefined(env, &jsContext->error);
232 if (!context->bRetBool) {
233 napi_create_object(env, &callbackObj);
234 napi_create_int32(env, context->uiExtCallback->GetResultCode(), &resultCode);
235 napi_set_named_property(env, callbackObj, "resultCode", resultCode);
236 napi_create_string_utf8(env, context->uiExtCallback->GetResultUri().c_str(), NAPI_AUTO_LENGTH, &resultUri);
237 napi_set_named_property(env, callbackObj, "resultUri", resultUri);
238 napi_create_string_utf8(
239 env, context->uiExtCallback->GetResultMediaType().c_str(), NAPI_AUTO_LENGTH, &resultMediaType);
240 napi_set_named_property(env, callbackObj, "mediaType", resultMediaType);
241 jsContext->data = callbackObj;
242 } else {
243 napi_get_undefined(env, &jsContext->data);
244 }
245 }
246
247 if (!context->funcName.empty() && context->taskId > 0) {
248 // Finish async trace
249 CAMERA_FINISH_ASYNC_TRACE(context->funcName, context->taskId);
250 jsContext->funcName = context->funcName;
251 }
252
253 if (context->work != nullptr) {
254 CameraNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef, context->work, *jsContext);
255 }
256 delete context;
257 }
258
StartCameraAbility(napi_env env,std::shared_ptr<PickerContextProxy> pickerContextProxy,AAFwk::Want & want)259 static std::shared_ptr<UIExtensionCallback> StartCameraAbility(
260 napi_env env, std::shared_ptr<PickerContextProxy> pickerContextProxy, AAFwk::Want& want)
261 {
262 auto uiExtCallback = std::make_shared<UIExtensionCallback>(pickerContextProxy);
263 OHOS::Ace::ModalUIExtensionCallbacks extensionCallbacks = {
264 [uiExtCallback](int32_t releaseCode) { uiExtCallback->OnRelease(releaseCode); },
265 [uiExtCallback](int32_t resultCode, const OHOS::AAFwk::Want& result) {
266 uiExtCallback->OnResult(resultCode, result); },
267 [uiExtCallback](const OHOS::AAFwk::WantParams& request) { uiExtCallback->OnReceive(request); },
268 [uiExtCallback](int32_t errorCode, const std::string& name, const std::string& message) {
269 uiExtCallback->OnError(errorCode, name, message); },
270 [uiExtCallback](const std::shared_ptr<OHOS::Ace::ModalUIExtensionProxy>& uiProxy) {
271 uiExtCallback->OnRemoteReady(uiProxy); },
272 [uiExtCallback]() { uiExtCallback->OnDestroy(); }
273 };
274
275 AbilityRuntime::RuntimeTask task = [extensionCallbacks](
276 const int32_t code, const AAFwk::Want& returnWant, bool isInner) {
277 if (code == 0) {
278 extensionCallbacks.onResult(0, returnWant);
279 } else {
280 extensionCallbacks.onError(code, "", "");
281 }
282 MEDIA_INFO_LOG("picker StartCameraAbility get result %{public}d %{public}d", code, isInner);
283 };
284
285 auto ret = pickerContextProxy->StartAbilityForResult(want, 1, std::move(task));
286 if (ret != ERR_OK) {
287 MEDIA_ERR_LOG("picker StartCameraAbility picker StartCameraAbility is %{public}d", ret);
288 return nullptr;
289 }
290 return uiExtCallback;
291 }
292
StartAsyncWork(napi_env env,CameraPickerAsyncContext * pickerAsyncCtx)293 static napi_status StartAsyncWork(napi_env env, CameraPickerAsyncContext* pickerAsyncCtx)
294 {
295 napi_value resource = nullptr;
296 CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Pick");
297 MEDIA_INFO_LOG("CameraPicker StartAsyncWork");
298 return napi_create_async_work(
299 env, nullptr, resource,
300 [](napi_env env, void* data) {
301 MEDIA_INFO_LOG("CameraPicker wait result begin");
302 auto context = static_cast<CameraPickerAsyncContext*>(data);
303 context->status = false;
304 // Start async trace
305
306 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
307 context->bRetBool = false;
308
309 context->uiExtCallback->WaitResultLock();
310 MEDIA_INFO_LOG("CameraPicker wait result end");
311 context->status = true;
312 },
313 CommonCompleteCallback, static_cast<void*>(pickerAsyncCtx), &pickerAsyncCtx->work);
314 }
315
Pick(napi_env env,napi_callback_info cbInfo)316 napi_value CameraPickerNapi::Pick(napi_env env, napi_callback_info cbInfo)
317 {
318 MEDIA_INFO_LOG("CameraPicker::Pick is called");
319 CAMERA_SYNC_TRACE;
320 napi_value result = nullptr;
321 size_t argc = ARGS_THREE;
322 napi_value argv[ARGS_THREE];
323 napi_value thisVar = nullptr;
324
325 napi_get_undefined(env, &result);
326 if (napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr) != napi_ok) {
327 MEDIA_ERR_LOG("napi_get_cb_info failed");
328 return result;
329 }
330
331 if (argc < ARGS_THREE) {
332 MEDIA_ERR_LOG("the parameter of number should be at least three");
333 return result;
334 }
335
336 std::unique_ptr<CameraPickerAsyncContext> asyncCtx = std::make_unique<CameraPickerAsyncContext>();
337 asyncCtx->funcName = "CameraPickerNapi::Pick";
338 asyncCtx->taskId = CameraNapiUtils::IncrementAndGet(cameraPickerTaskId);
339 asyncCtx->contextProxy = GetAbilityContext(env, argv[ARGS_ZERO]);
340 if (asyncCtx->contextProxy == nullptr) {
341 MEDIA_ERR_LOG("GetAbilityContext failed");
342 return result;
343 }
344
345 std::vector<PickerMediaType> mediaTypes;
346 if (!GetMediaTypes(env, argv[ARGS_ONE], mediaTypes)) {
347 MEDIA_ERR_LOG("GetMediaTypes failed");
348 return result;
349 }
350
351 if (!GetPickerProfile(env, argv[ARGS_TWO], asyncCtx->pickerProfile)) {
352 MEDIA_ERR_LOG("GetPhotoProfiles failed");
353 return result;
354 }
355 SetPickerWantParams(asyncCtx->want, asyncCtx->contextProxy, mediaTypes, asyncCtx->pickerProfile);
356 asyncCtx->uiExtCallback = StartCameraAbility(env, asyncCtx->contextProxy, asyncCtx->want);
357 if (asyncCtx->uiExtCallback == nullptr) {
358 MEDIA_ERR_LOG("StartCameraAbility failed");
359 return result;
360 }
361 CAMERA_NAPI_CREATE_PROMISE(env, asyncCtx->callbackRef, asyncCtx->deferred, result);
362 if (StartAsyncWork(env, asyncCtx.get()) != napi_ok) {
363 MEDIA_ERR_LOG("Failed to create napi_create_async_work for Pick");
364 napi_get_undefined(env, &result);
365 } else {
366 napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated);
367 asyncCtx.release();
368 }
369 return result;
370 }
371
Init(napi_env env,napi_value exports)372 napi_value CameraPickerNapi::Init(napi_env env, napi_value exports)
373 {
374 MEDIA_INFO_LOG("CameraPickerNapi::Init is called");
375 napi_status status;
376 napi_value ctorObj;
377 int32_t refCount = 1;
378
379 napi_property_descriptor camera_picker_props[] = {};
380
381 napi_property_descriptor camera_picker_static_props[] = {
382 DECLARE_NAPI_STATIC_FUNCTION("pick", Pick),
383 DECLARE_NAPI_PROPERTY("PickerMediaType", CreatePickerMediaType(env)),
384 DECLARE_NAPI_STATIC_PROPERTY("PickerProfile", CreatePickerProfile(env)),
385 DECLARE_NAPI_STATIC_PROPERTY("PickerResult", CreatePickerResult(env)),
386 };
387
388 status = napi_define_class(env, CAMERA_PICKER_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH, CameraPickerNapiConstructor,
389 nullptr, sizeof(camera_picker_props) / sizeof(camera_picker_props[PARAM0]), camera_picker_props, &ctorObj);
390 if (status == napi_ok) {
391 if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
392 status = napi_set_named_property(env, exports, CAMERA_PICKER_NAPI_CLASS_NAME, ctorObj);
393 if (status == napi_ok &&
394 napi_define_properties(env, exports,
395 sizeof(camera_picker_static_props) / sizeof(camera_picker_static_props[PARAM0]),
396 camera_picker_static_props) == napi_ok) {
397 return exports;
398 }
399 }
400 }
401 MEDIA_ERR_LOG("Init call Failed!");
402 return nullptr;
403 }
404
CreatePickerProfile(napi_env env)405 napi_value CameraPickerNapi::CreatePickerProfile(napi_env env)
406 {
407 MEDIA_DEBUG_LOG("CreatePickerProfile is called");
408 napi_value result = nullptr;
409 napi_status status;
410 napi_property_descriptor pickerProfileProps[] = {
411 DECLARE_NAPI_PROPERTY("cameraPosition", nullptr),
412 DECLARE_NAPI_PROPERTY("saveUri", nullptr),
413 DECLARE_NAPI_PROPERTY("videoDuration", nullptr),
414 };
415
416 status = napi_define_class(
417 env, "PickerProfile", NAPI_AUTO_LENGTH,
418 [](napi_env env, napi_callback_info info) {
419 MEDIA_DEBUG_LOG("PickerProfileConstructor is called");
420 napi_status status;
421 napi_value result = nullptr;
422 napi_value thisVar = nullptr;
423
424 napi_get_undefined(env, &result);
425 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
426 if (status == napi_ok) {
427 return thisVar;
428 }
429 return result;
430 },
431 nullptr, sizeof(pickerProfileProps) / sizeof(pickerProfileProps[PARAM0]), pickerProfileProps, &result);
432 if (status != napi_ok) {
433 MEDIA_DEBUG_LOG("CreatePickerProfile class fail");
434 napi_get_undefined(env, &result);
435 }
436 return result;
437 }
438
CreatePickerMediaType(napi_env env)439 napi_value CameraPickerNapi::CreatePickerMediaType(napi_env env)
440 {
441 MEDIA_DEBUG_LOG("CreatePickerMediaType is called");
442 napi_value result = nullptr;
443 napi_status status;
444 if (mediaTypeRef_ != nullptr) {
445 status = napi_get_reference_value(env, mediaTypeRef_, &result);
446 if (status == napi_ok) {
447 return result;
448 }
449 }
450 status = CameraNapiUtils::CreateObjectWithPropNameAndValues(env, &result,
451 sizeof(PICKER_MEDIA_TYPE) / sizeof(PICKER_MEDIA_TYPE[0]), const_cast<const char**>(PICKER_MEDIA_TYPE),
452 PICKER_MEDIA_TYPE_VALUE);
453 if (status != napi_ok) {
454 MEDIA_DEBUG_LOG("CreatePickerMediaType call end!");
455 napi_get_undefined(env, &result);
456 } else {
457 napi_create_reference(env, result, 1, &mediaTypeRef_);
458 }
459 return result;
460 }
461
CreatePickerResult(napi_env env)462 napi_value CameraPickerNapi::CreatePickerResult(napi_env env)
463 {
464 MEDIA_DEBUG_LOG("CreatePickerResult is called");
465 napi_value result = nullptr;
466 napi_status status;
467 napi_property_descriptor pickerResultProps[] = {
468 DECLARE_NAPI_PROPERTY("resultCode", nullptr),
469 DECLARE_NAPI_PROPERTY("resultUri", nullptr),
470 DECLARE_NAPI_PROPERTY("mediaType", nullptr),
471 };
472
473 status = napi_define_class(
474 env, "PickerResult", NAPI_AUTO_LENGTH,
475 [](napi_env env, napi_callback_info info) {
476 MEDIA_DEBUG_LOG("PickerResultConstructor is called");
477 napi_status status;
478 napi_value result = nullptr;
479 napi_value thisVar = nullptr;
480
481 napi_get_undefined(env, &result);
482 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
483 if (status == napi_ok) {
484 return thisVar;
485 }
486 return result;
487 },
488 nullptr, sizeof(pickerResultProps) / sizeof(pickerResultProps[PARAM0]), pickerResultProps, &result);
489 if (status != napi_ok) {
490 MEDIA_DEBUG_LOG("CreatePickerResult class fail");
491 napi_get_undefined(env, &result);
492 }
493 return result;
494 }
495
496 // Constructor callback
CameraPickerNapiConstructor(napi_env env,napi_callback_info info)497 napi_value CameraPickerNapi::CameraPickerNapiConstructor(napi_env env, napi_callback_info info)
498 {
499 MEDIA_DEBUG_LOG("CameraPickerNapiConstructor is called");
500 napi_status status;
501 napi_value result = nullptr;
502 napi_value thisVar = nullptr;
503
504 napi_get_undefined(env, &result);
505 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
506
507 if (status == napi_ok && thisVar != nullptr) {
508 std::unique_ptr<CameraPickerNapi> obj = std::make_unique<CameraPickerNapi>();
509 obj->env_ = env;
510 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
511 CameraPickerNapi::CameraPickerNapiDestructor, nullptr, nullptr);
512 if (status == napi_ok) {
513 obj.release();
514 return thisVar;
515 } else {
516 MEDIA_ERR_LOG("Failure wrapping js to native napi");
517 }
518 }
519 MEDIA_ERR_LOG("CameraPickerNapiConstructor call Failed!");
520 return result;
521 }
522
CameraPickerNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)523 void CameraPickerNapi::CameraPickerNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
524 {
525 MEDIA_DEBUG_LOG("CameraPickerNapiDestructor is called");
526 CameraPickerNapi* camera = reinterpret_cast<CameraPickerNapi*>(nativeObject);
527 if (camera != nullptr) {
528 delete camera;
529 }
530 }
531
UIExtensionCallback(std::shared_ptr<PickerContextProxy> contextProxy)532 UIExtensionCallback::UIExtensionCallback(std::shared_ptr<PickerContextProxy> contextProxy) : contextProxy_(contextProxy)
533 {}
534
FinishPicker(int32_t code)535 bool UIExtensionCallback::FinishPicker(int32_t code)
536 {
537 {
538 std::unique_lock<std::mutex> lock(cbMutex_);
539 if (isCallbackReturned_) {
540 MEDIA_ERR_LOG("alreadyCallback");
541 return false;
542 }
543 isCallbackReturned_ = true;
544 }
545 resultCode_ = code;
546 CloseWindow();
547 NotifyResultLock();
548 return true;
549 }
550
OnRelease(int32_t releaseCode)551 void UIExtensionCallback::OnRelease(int32_t releaseCode)
552 {
553 MEDIA_INFO_LOG("UIExtensionComponent OnRelease(), releaseCode = %{public}d", releaseCode);
554 FinishPicker(releaseCode);
555 }
556
OnResult(int32_t resultCode,const OHOS::AAFwk::Want & result)557 void UIExtensionCallback::OnResult(int32_t resultCode, const OHOS::AAFwk::Want& result)
558 {
559 const AAFwk::WantParams& wantParams = result.GetParams();
560 std::string uri = wantParams.GetStringParam("resourceUri");
561 std::string resourceMode = wantParams.GetStringParam("mode");
562 MEDIA_INFO_LOG("OnResult is called,resultCode = %{public}d, uri = %{public}s ,CaptureMode:%{public}s", resultCode,
563 uri.c_str(), resourceMode.c_str());
564 resultUri_ = uri;
565 resultMode_ = resourceMode;
566 FinishPicker(resultCode);
567 }
568
OnReceive(const OHOS::AAFwk::WantParams & request)569 void UIExtensionCallback::OnReceive(const OHOS::AAFwk::WantParams& request)
570 {
571 MEDIA_INFO_LOG("UIExtensionComponent OnReceive()");
572 }
573
OnError(int32_t errorCode,const std::string & name,const std::string & message)574 void UIExtensionCallback::OnError(int32_t errorCode, const std::string& name, const std::string& message)
575 {
576 MEDIA_INFO_LOG("UIExtensionComponent OnError(), errorCode = %{public}d, name = %{public}s, message = %{public}s",
577 errorCode, name.c_str(), message.c_str());
578 FinishPicker(errorCode);
579 }
580
OnRemoteReady(const std::shared_ptr<OHOS::Ace::ModalUIExtensionProxy> & uiProxy)581 void UIExtensionCallback::OnRemoteReady(const std::shared_ptr<OHOS::Ace::ModalUIExtensionProxy>& uiProxy)
582 {
583 MEDIA_INFO_LOG("UIExtensionComponent OnRemoteReady()");
584 }
585
OnDestroy()586 void UIExtensionCallback::OnDestroy()
587 {
588 MEDIA_INFO_LOG("UIExtensionComponent OnDestroy()");
589 FinishPicker(0);
590 }
591
CloseWindow()592 void UIExtensionCallback::CloseWindow()
593 {
594 MEDIA_INFO_LOG("start CloseWindow");
595 if (contextProxy_ == nullptr) {
596 MEDIA_ERR_LOG("contextProxy_ is nullptr");
597 return;
598 }
599 if (sessionId_ == 0) {
600 MEDIA_WARNING_LOG("sessionId_ is 0");
601 return;
602 }
603 auto uiContent = contextProxy_->GetUIContent();
604 if (uiContent != nullptr) {
605 MEDIA_INFO_LOG("CloseModalUIExtension");
606 uiContent->CloseModalUIExtension(sessionId_);
607 }
608 }
609 } // namespace CameraStandard
610 } // namespace OHOS