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