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