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