1 /*
2 * Copyright (C) 2024 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 #define MLOG_TAG "CloudMediaAssetManagerNapi"
17
18 #include "cloud_media_asset_manager_napi.h"
19
20 #include "media_column.h"
21 #include "medialibrary_client_errno.h"
22 #include "medialibrary_errno.h"
23 #include "medialibrary_napi_log.h"
24 #include "medialibrary_tracer.h"
25 #include "userfile_client.h"
26 #include "userfile_manager_types.h"
27 #include "media_library_napi.h"
28 #include "media_file_uri.h"
29 #include "media_file_utils.h"
30 #include "result_set_utils.h"
31 #include "cloud_media_asset_types.h"
32 #include "cloud_media_asset_status_napi.h"
33
34 using namespace std;
35 namespace OHOS::Media {
36 static const string CLOUD_MEDIA_ASSET_MANAGER_CLASS = "CloudMediaAssetManager";
37 thread_local napi_ref CloudMediaAssetManagerNapi::constructor_ = nullptr;
38 const size_t TYPE_SIZE = 6;
39 const int32_t INDEX_ZERO = 0;
40 const int32_t INDEX_ONE = 1;
41 const int32_t INDEX_TWO = 2;
42 const int32_t INDEX_THREE = 3;
43 const int32_t INDEX_FOUR = 4;
44 const int32_t INDEX_FIVE = 5;
45
Init(napi_env env,napi_value exports)46 napi_value CloudMediaAssetManagerNapi::Init(napi_env env, napi_value exports)
47 {
48 NapiClassInfo info = {
49 .name = CLOUD_MEDIA_ASSET_MANAGER_CLASS,
50 .ref = &constructor_,
51 .constructor = Constructor,
52 .props = {
53 DECLARE_NAPI_STATIC_FUNCTION("getCloudMediaAssetManagerInstance", JSGetCloudMediaAssetManagerInstance),
54 DECLARE_NAPI_FUNCTION("startDownloadCloudMedia", JSStartDownloadCloudMedia),
55 DECLARE_NAPI_FUNCTION("pauseDownloadCloudMedia", JSPauseDownloadCloudMedia),
56 DECLARE_NAPI_FUNCTION("cancelDownloadCloudMedia", JSCancelDownloadCloudMedia),
57 DECLARE_NAPI_FUNCTION("retainCloudMediaAsset", JSRetainCloudMediaAsset),
58 DECLARE_NAPI_FUNCTION("getCloudMediaAssetStatus", JSGetCloudMediaAssetStatus),
59 } };
60 MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
61 return exports;
62 }
63
Constructor(napi_env env,napi_callback_info info)64 napi_value CloudMediaAssetManagerNapi::Constructor(napi_env env, napi_callback_info info)
65 {
66 if (!MediaLibraryNapiUtils::IsSystemApp()) {
67 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL,
68 "The cloud media asset manager instance can be called only by system apps");
69 return nullptr;
70 }
71 napi_value newTarget = nullptr;
72 CHECK_ARGS(env, napi_get_new_target(env, info, &newTarget), JS_INNER_FAIL);
73 CHECK_COND_RET(newTarget != nullptr, nullptr, "Failed to check new.target");
74
75 size_t argc = ARGS_ONE;
76 napi_value argv[ARGS_ONE] = { 0 };
77 napi_value thisVar = nullptr;
78 CHECK_ARGS(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr), JS_INNER_FAIL);
79 CHECK_COND_WITH_MESSAGE(env, argc == ARGS_ONE, "Number of args is invalid");
80 if (!InitUserFileClient(env, info)) {
81 NAPI_ERR_LOG("Failed to init UserFileClient");
82 return nullptr;
83 }
84
85 unique_ptr<CloudMediaAssetManagerNapi> obj = make_unique<CloudMediaAssetManagerNapi>();
86 CHECK_COND(env, obj != nullptr, JS_INNER_FAIL);
87 CHECK_ARGS(env,
88 napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()), CloudMediaAssetManagerNapi::Destructor, nullptr,
89 nullptr),
90 JS_INNER_FAIL);
91 obj.release();
92 return thisVar;
93 }
94
Destructor(napi_env env,void * nativeObject,void * finalizeHint)95 void CloudMediaAssetManagerNapi::Destructor(napi_env env, void* nativeObject, void* finalizeHint)
96 {
97 auto* cloudMediaAssetManager = reinterpret_cast<CloudMediaAssetManagerNapi*>(nativeObject);
98 if (cloudMediaAssetManager == nullptr) {
99 NAPI_ERR_LOG("cloudMediaAssetManager is nullptr");
100 return;
101 }
102 delete cloudMediaAssetManager;
103 cloudMediaAssetManager = nullptr;
104 }
105
CheckWhetherInitSuccess(napi_env env,napi_value value,bool checkIsValid)106 static bool CheckWhetherInitSuccess(napi_env env, napi_value value, bool checkIsValid)
107 {
108 napi_value propertyNames;
109 uint32_t propertyLength;
110 napi_valuetype valueType = napi_undefined;
111 NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false);
112 if (valueType != napi_object) {
113 NAPI_ERR_LOG("valueType is not valid");
114 return false;
115 }
116
117 NAPI_CALL_BASE(env, napi_get_property_names(env, value, &propertyNames), false);
118 NAPI_CALL_BASE(env, napi_get_array_length(env, propertyNames, &propertyLength), false);
119 if (propertyLength == 0) {
120 NAPI_ERR_LOG("propertyLength is 0");
121 return false;
122 }
123 if (checkIsValid && (!UserFileClient::IsValid())) {
124 NAPI_ERR_LOG("UserFileClient is not valid");
125 return false;
126 }
127 return true;
128 }
129
JSGetCloudMediaAssetManagerInstance(napi_env env,napi_callback_info info)130 napi_value CloudMediaAssetManagerNapi::JSGetCloudMediaAssetManagerInstance(napi_env env, napi_callback_info info)
131 {
132 MediaLibraryTracer tracer;
133 tracer.Start("GetCloudMediaAssetManagerInstance");
134
135 constexpr size_t ARG_CONTEXT = 1;
136 size_t argc = ARG_CONTEXT;
137 napi_value argv[ARGS_TWO] = {0};
138
139 napi_value thisVar = nullptr;
140 napi_value ctor = nullptr;
141 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
142 NAPI_CALL(env, napi_get_reference_value(env, constructor_, &ctor));
143
144 napi_value result = nullptr;
145 NAPI_CALL(env, napi_new_instance(env, ctor, argc, argv, &result));
146 if (!CheckWhetherInitSuccess(env, result, false)) {
147 NAPI_ERR_LOG("Init Cloud Media Asset Manager Instance is failed");
148 NAPI_CALL(env, napi_get_undefined(env, &result));
149 }
150 return result;
151 }
152
InitUserFileClient(napi_env env,napi_callback_info info)153 bool CloudMediaAssetManagerNapi::InitUserFileClient(napi_env env, napi_callback_info info)
154 {
155 if (UserFileClient::IsValid()) {
156 return true;
157 }
158
159 std::unique_lock<std::mutex> helperLock(MediaLibraryNapi::sUserFileClientMutex_);
160 if (!UserFileClient::IsValid()) {
161 UserFileClient::Init(env, info);
162 }
163 helperLock.unlock();
164 return UserFileClient::IsValid();
165 }
166
ParseArgCloudMediaDownloadType(napi_env env,napi_callback_info info,unique_ptr<CloudMediaAssetAsyncContext> & context)167 static napi_status ParseArgCloudMediaDownloadType(napi_env env, napi_callback_info info,
168 unique_ptr<CloudMediaAssetAsyncContext>& context)
169 {
170 CHECK_STATUS_RET(MediaLibraryNapiUtils::AsyncContextGetArgs(env, info, context, ARGS_ONE, ARGS_ONE),
171 "Failed to get args");
172 napi_valuetype valueType = napi_undefined;
173 CHECK_STATUS_RET(napi_typeof(env, context->argv[ARGS_ZERO], &valueType), "Failed to get type");
174 CHECK_COND_RET(valueType == napi_number, napi_number_expected, "Type is not as expected number");
175 CHECK_STATUS_RET(napi_get_value_int32(env, context->argv[ARGS_ZERO], &context->cloudMediaDownloadType),
176 "Failed to get int32 value");
177 return napi_ok;
178 }
179
ParseArgCloudMediaRetainType(napi_env env,napi_callback_info info,unique_ptr<CloudMediaAssetAsyncContext> & context)180 static napi_status ParseArgCloudMediaRetainType(napi_env env, napi_callback_info info,
181 unique_ptr<CloudMediaAssetAsyncContext>& context)
182 {
183 CHECK_STATUS_RET(MediaLibraryNapiUtils::AsyncContextGetArgs(env, info, context, ARGS_ONE, ARGS_ONE),
184 "Failed to get args");
185 napi_valuetype valueType = napi_undefined;
186 CHECK_STATUS_RET(napi_typeof(env, context->argv[ARGS_ZERO], &valueType), "Failed to get type");
187 CHECK_COND_RET(valueType == napi_number, napi_number_expected, "Type is not as expected number");
188 CHECK_STATUS_RET(napi_get_value_int32(env, context->argv[ARGS_ZERO], &context->cloudMediaRetainType),
189 "Failed to get int32 value");
190 return napi_ok;
191 }
192
StartDownloadCloudMediaExecute(napi_env env,void * data)193 static void StartDownloadCloudMediaExecute(napi_env env, void* data)
194 {
195 MediaLibraryTracer tracer;
196 tracer.Start("StartDownloadCloudMediaExecute");
197 NAPI_INFO_LOG("enter StartDownloadCloudMediaExecute");
198
199 auto* context = static_cast<CloudMediaAssetAsyncContext*>(data);
200 auto downloadType = context->cloudMediaDownloadType;
201 string uriStr;
202 if (downloadType == static_cast<int32_t>(CloudMediaDownloadType::DOWNLOAD_FORCE)) {
203 uriStr = CMAM_CLOUD_MEDIA_ASSET_TASK_START_FORCE;
204 } else if (downloadType == static_cast<int32_t>(CloudMediaDownloadType::DOWNLOAD_GENTLE)) {
205 uriStr = CMAM_CLOUD_MEDIA_ASSET_TASK_START_GENTLE;
206 } else {
207 NAPI_ERR_LOG("cloudMediaDownloadType error, err type: %{public}d", downloadType);
208 return;
209 }
210 Uri startUri(uriStr);
211 int32_t changedRows = UserFileClient::Update(startUri, context->predicates, context->valuesBucket);
212 if (changedRows < 0) {
213 context->SaveError(changedRows);
214 NAPI_ERR_LOG("Start download cloud media failed, err: %{public}d", changedRows);
215 }
216 }
217
StartDownloadCloudMediaCompleteCallback(napi_env env,napi_status status,void * data)218 static void StartDownloadCloudMediaCompleteCallback(napi_env env, napi_status status, void* data)
219 {
220 auto* context = static_cast<CloudMediaAssetAsyncContext*>(data);
221 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
222 auto jsContext = make_unique<JSAsyncContextOutput>();
223 jsContext->status = false;
224 napi_get_undefined(env, &jsContext->data);
225 napi_get_undefined(env, &jsContext->error);
226 if (context->error == ERR_DEFAULT) {
227 jsContext->status = true;
228 } else {
229 context->HandleError(env, jsContext->error);
230 }
231
232 if (context->work != nullptr) {
233 MediaLibraryNapiUtils::InvokeJSAsyncMethod(
234 env, context->deferred, context->callbackRef, context->work, *jsContext);
235 }
236 delete context;
237 }
238
JSStartDownloadCloudMedia(napi_env env,napi_callback_info info)239 napi_value CloudMediaAssetManagerNapi::JSStartDownloadCloudMedia(napi_env env, napi_callback_info info)
240 {
241 if (!MediaLibraryNapiUtils::IsSystemApp()) {
242 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
243 return nullptr;
244 }
245 MediaLibraryTracer tracer;
246 tracer.Start("JSStartDownloadCloudMedia");
247
248 auto asyncContext = make_unique<CloudMediaAssetAsyncContext>();
249 CHECK_COND_WITH_MESSAGE(env, ParseArgCloudMediaDownloadType(env, info, asyncContext) == napi_ok,
250 "Failed to parse args");
251 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "StartDownloadCloudMedia",
252 StartDownloadCloudMediaExecute, StartDownloadCloudMediaCompleteCallback);
253 }
254
PauseDownloadCloudMediaExecute(napi_env env,void * data)255 static void PauseDownloadCloudMediaExecute(napi_env env, void* data)
256 {
257 MediaLibraryTracer tracer;
258 tracer.Start("PauseDownloadCloudMediaExecute");
259 NAPI_INFO_LOG("enter PauseDownloadCloudMediaExecute");
260
261 auto* context = static_cast<CloudMediaAssetAsyncContext*>(data);
262 Uri pauseUri(CMAM_CLOUD_MEDIA_ASSET_TASK_PAUSE);
263 int32_t changedRows = UserFileClient::Update(pauseUri, context->predicates, context->valuesBucket);
264 if (changedRows < 0) {
265 context->SaveError(changedRows);
266 NAPI_ERR_LOG("Pause download cloud media failed, err: %{public}d", changedRows);
267 }
268 }
269
PauseDownloadCloudMediaCompleteCallback(napi_env env,napi_status status,void * data)270 static void PauseDownloadCloudMediaCompleteCallback(napi_env env, napi_status status, void* data)
271 {
272 auto* context = static_cast<CloudMediaAssetAsyncContext*>(data);
273 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
274 auto jsContext = make_unique<JSAsyncContextOutput>();
275 jsContext->status = false;
276 napi_get_undefined(env, &jsContext->data);
277 napi_get_undefined(env, &jsContext->error);
278 if (context->error == ERR_DEFAULT) {
279 jsContext->status = true;
280 } else {
281 context->HandleError(env, jsContext->error);
282 }
283
284 if (context->work != nullptr) {
285 MediaLibraryNapiUtils::InvokeJSAsyncMethod(
286 env, context->deferred, context->callbackRef, context->work, *jsContext);
287 }
288 delete context;
289 }
290
JSPauseDownloadCloudMedia(napi_env env,napi_callback_info info)291 napi_value CloudMediaAssetManagerNapi::JSPauseDownloadCloudMedia(napi_env env, napi_callback_info info)
292 {
293 if (!MediaLibraryNapiUtils::IsSystemApp()) {
294 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
295 return nullptr;
296 }
297 MediaLibraryTracer tracer;
298 tracer.Start("JSPauseDownloadCloudMedia");
299
300 auto asyncContext = make_unique<CloudMediaAssetAsyncContext>();
301 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "PauseDownloadCloudMedia",
302 PauseDownloadCloudMediaExecute, PauseDownloadCloudMediaCompleteCallback);
303 }
304
CancelDownloadCloudMediaExecute(napi_env env,void * data)305 static void CancelDownloadCloudMediaExecute(napi_env env, void* data)
306 {
307 MediaLibraryTracer tracer;
308 tracer.Start("CancelDownloadCloudMediaExecute");
309 NAPI_INFO_LOG("enter CancelDownloadCloudMediaExecute");
310
311 auto* context = static_cast<CloudMediaAssetAsyncContext*>(data);
312 Uri cancelUri(CMAM_CLOUD_MEDIA_ASSET_TASK_CANCEL);
313 int32_t changedRows = UserFileClient::Update(cancelUri, context->predicates, context->valuesBucket);
314 if (changedRows < 0) {
315 context->SaveError(changedRows);
316 NAPI_ERR_LOG("Cancel download cloud media failed, err: %{public}d", changedRows);
317 }
318 }
319
CancelDownloadCloudMediaCompleteCallback(napi_env env,napi_status status,void * data)320 static void CancelDownloadCloudMediaCompleteCallback(napi_env env, napi_status status, void* data)
321 {
322 auto* context = static_cast<CloudMediaAssetAsyncContext*>(data);
323 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
324 auto jsContext = make_unique<JSAsyncContextOutput>();
325 jsContext->status = false;
326 napi_get_undefined(env, &jsContext->data);
327 napi_get_undefined(env, &jsContext->error);
328 if (context->error == ERR_DEFAULT) {
329 jsContext->status = true;
330 } else {
331 context->HandleError(env, jsContext->error);
332 }
333
334 if (context->work != nullptr) {
335 MediaLibraryNapiUtils::InvokeJSAsyncMethod(
336 env, context->deferred, context->callbackRef, context->work, *jsContext);
337 }
338 delete context;
339 }
340
JSCancelDownloadCloudMedia(napi_env env,napi_callback_info info)341 napi_value CloudMediaAssetManagerNapi::JSCancelDownloadCloudMedia(napi_env env, napi_callback_info info)
342 {
343 if (!MediaLibraryNapiUtils::IsSystemApp()) {
344 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
345 return nullptr;
346 }
347 MediaLibraryTracer tracer;
348 tracer.Start("JSCancelDownloadCloudMedia");
349
350 auto asyncContext = make_unique<CloudMediaAssetAsyncContext>();
351 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "CancelDownloadCloudMedia",
352 CancelDownloadCloudMediaExecute, CancelDownloadCloudMediaCompleteCallback);
353 }
354
RetainCloudMediaAssetExecute(napi_env env,void * data)355 static void RetainCloudMediaAssetExecute(napi_env env, void* data)
356 {
357 MediaLibraryTracer tracer;
358 tracer.Start("RetainCloudMediaAssetExecute");
359 NAPI_INFO_LOG("enter RetainCloudMediaAssetExecute");
360
361 auto* context = static_cast<CloudMediaAssetAsyncContext*>(data);
362 auto retainType = context->cloudMediaRetainType;
363 string uriStr;
364 if (retainType == static_cast<int32_t>(CloudMediaRetainType::RETAIN_FORCE)) {
365 uriStr = CMAM_CLOUD_MEDIA_ASSET_TASK_RETAIN_FORCE;
366 } else {
367 NAPI_ERR_LOG("cloudMediaRetainType error, err type: %{public}d", retainType);
368 return;
369 }
370 Uri retainUri(uriStr);
371 int32_t changedRows = UserFileClient::Update(retainUri, context->predicates, context->valuesBucket);
372 if (changedRows < 0) {
373 context->SaveError(changedRows);
374 NAPI_ERR_LOG("Retain cloud media asset failed, err: %{public}d", changedRows);
375 }
376 }
377
RetainCloudMediaAssetCompleteCallback(napi_env env,napi_status status,void * data)378 static void RetainCloudMediaAssetCompleteCallback(napi_env env, napi_status status, void* data)
379 {
380 auto* context = static_cast<CloudMediaAssetAsyncContext*>(data);
381 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
382 auto jsContext = make_unique<JSAsyncContextOutput>();
383 jsContext->status = false;
384 napi_get_undefined(env, &jsContext->data);
385 napi_get_undefined(env, &jsContext->error);
386 if (context->error == ERR_DEFAULT) {
387 jsContext->status = true;
388 } else {
389 context->HandleError(env, jsContext->error);
390 }
391
392 if (context->work != nullptr) {
393 MediaLibraryNapiUtils::InvokeJSAsyncMethod(
394 env, context->deferred, context->callbackRef, context->work, *jsContext);
395 }
396 delete context;
397 }
398
JSRetainCloudMediaAsset(napi_env env,napi_callback_info info)399 napi_value CloudMediaAssetManagerNapi::JSRetainCloudMediaAsset(napi_env env, napi_callback_info info)
400 {
401 if (!MediaLibraryNapiUtils::IsSystemApp()) {
402 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
403 return nullptr;
404 }
405 MediaLibraryTracer tracer;
406 tracer.Start("JSRetainCloudMediaAsset");
407
408 auto asyncContext = make_unique<CloudMediaAssetAsyncContext>();
409 CHECK_COND_WITH_MESSAGE(env, ParseArgCloudMediaRetainType(env, info, asyncContext) == napi_ok,
410 "Failed to parse args");
411 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "RetainCloudMediaAsset",
412 RetainCloudMediaAssetExecute, RetainCloudMediaAssetCompleteCallback);
413 }
414
CanConvertToInt32(const std::string & str)415 static bool CanConvertToInt32(const std::string &str)
416 {
417 std::istringstream stringStream(str);
418 int32_t num = 0;
419 stringStream >> num;
420 return stringStream.eof() && !stringStream.fail();
421 }
422
SplitUriString(const std::string & str,std::vector<std::string> & type)423 static bool SplitUriString(const std::string& str, std::vector<std::string> &type)
424 {
425 std::stringstream ss(str);
426 std::string item;
427 while (std::getline(ss, item, ',')) {
428 if (item.empty()) {
429 return false;
430 }
431 type.emplace_back(item);
432 }
433 return type.size() == TYPE_SIZE;
434 }
435
GetCloudMediaAssetStatusExecute(napi_env env,void * data)436 static void GetCloudMediaAssetStatusExecute(napi_env env, void* data)
437 {
438 MediaLibraryTracer tracer;
439 tracer.Start("GetCloudMediaAssetStatusExecute");
440 NAPI_INFO_LOG("enter GetCloudMediaAssetStatusExecute");
441
442 auto* context = static_cast<CloudMediaAssetAsyncContext*>(data);
443 Uri getUri(CMAM_CLOUD_MEDIA_ASSET_TASK_STATUS_QUERY);
444 string result = UserFileClient::GetType(getUri);
445 NAPI_INFO_LOG("Get cloud media asset, res: %{public}s.", result.c_str());
446 std::vector<std::string> type;
447 if (!SplitUriString(result, type)) {
448 NAPI_ERR_LOG("GetType failed");
449 return;
450 }
451 if (!CanConvertToInt32(type[INDEX_ZERO]) || !CanConvertToInt32(type[INDEX_FIVE])) {
452 NAPI_ERR_LOG("GetType failed");
453 return;
454 }
455 context->cloudMediaAssetTaskStatus_ = static_cast<CloudMediaAssetTaskStatus>(std::stoi(type[INDEX_ZERO]));
456 context->cloudMediaTaskPauseCause_ = static_cast<CloudMediaTaskPauseCause>(std::stoi(type[INDEX_FIVE]));
457 std::string taskInfo = "totalcount: " + type[INDEX_ONE] + "," +
458 "totalSize: " + type[INDEX_TWO] + "," +
459 "remainCount: " + type[INDEX_THREE] + "," +
460 "remainSize: " + type[INDEX_FOUR];
461 context->taskInfo_ = taskInfo;
462 }
463
GetCloudMediaAssetStatusCompleteCallback(napi_env env,napi_status status,void * data)464 static void GetCloudMediaAssetStatusCompleteCallback(napi_env env, napi_status status, void* data)
465 {
466 auto* context = static_cast<CloudMediaAssetAsyncContext*>(data);
467 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
468 auto jsContext = make_unique<JSAsyncContextOutput>();
469 jsContext->status = false;
470 napi_get_undefined(env, &jsContext->data);
471 napi_get_undefined(env, &jsContext->error);
472 if (context->error == ERR_DEFAULT) {
473 napi_value cloudMediaAssetStatus = CloudMediaAssetStatusNapi::NewCloudMediaAssetStatusNapi(env, context);
474 jsContext->data = cloudMediaAssetStatus;
475 jsContext->status = true;
476 } else {
477 context->HandleError(env, jsContext->error);
478 }
479
480 if (context->work != nullptr) {
481 MediaLibraryNapiUtils::InvokeJSAsyncMethod(
482 env, context->deferred, context->callbackRef, context->work, *jsContext);
483 }
484 delete context;
485 }
486
JSGetCloudMediaAssetStatus(napi_env env,napi_callback_info info)487 napi_value CloudMediaAssetManagerNapi::JSGetCloudMediaAssetStatus(napi_env env, napi_callback_info info)
488 {
489 if (!MediaLibraryNapiUtils::IsSystemApp()) {
490 NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps");
491 return nullptr;
492 }
493 MediaLibraryTracer tracer;
494 tracer.Start("JSGetCloudMediaAssetStatus");
495
496 auto asyncContext = make_unique<CloudMediaAssetAsyncContext>();
497 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "GetCloudMediaAssetStatus",
498 GetCloudMediaAssetStatusExecute, GetCloudMediaAssetStatusCompleteCallback);
499 }
500 } // namespace OHOS::Media