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