• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 #define MLOG_TAG "MediaLibraryBackupNapi"
17 
18 #include <napi_base_context.h>
19 #include "medialibrary_backup_napi.h"
20 #include "application_context.h"
21 #include "backup_restore_service.h"
22 #include "js_native_api.h"
23 #include "medialibrary_client_errno.h"
24 #include "medialibrary_errno.h"
25 #include "medialibrary_napi_log.h"
26 #include "medialibrary_napi_utils.h"
27 
28 namespace OHOS {
29 namespace Media {
30 
31 using RestoreBlock = struct {
32     napi_env env;
33     std::weak_ptr<OHOS::AbilityRuntime::Context> context;
34     RestoreInfo restoreInfo;
35     napi_deferred nativeDeferred;
36 };
37 
38 using RestoreExBlock = struct {
39     napi_env env;
40     std::weak_ptr<OHOS::AbilityRuntime::Context> context;
41     RestoreInfo restoreInfo;
42     std::string restoreExInfo;
43     napi_deferred nativeDeferred;
44 };
45 
46 using BackupBlock = struct {
47     napi_env env;
48     int32_t sceneCode;
49     std::string galleryAppName;
50     std::string mediaAppName;
51     napi_deferred nativeDeferred;
52 };
53 
54 using BackupExBlock = struct {
55     napi_env env;
56     int32_t sceneCode;
57     std::string galleryAppName;
58     std::string mediaAppName;
59     napi_deferred nativeDeferred;
60     std::string backupInfo;
61     std::string backupExInfo;
62 };
63 
Init(napi_env env,napi_value exports)64 napi_value MediaLibraryBackupNapi::Init(napi_env env, napi_value exports)
65 {
66     NAPI_INFO_LOG("Init, MediaLibraryBackupNapi has been used.");
67     napi_property_descriptor media_library_properties[] = {
68         DECLARE_NAPI_FUNCTION("startRestore", JSStartRestore),
69         DECLARE_NAPI_FUNCTION("startRestoreEx", JSStartRestoreEx),
70         DECLARE_NAPI_FUNCTION("getBackupInfo", JSGetBackupInfo),
71         DECLARE_NAPI_FUNCTION("getProgressInfo", JSGetProgressInfo),
72         DECLARE_NAPI_FUNCTION("startBackup", JSStartBackup),
73         DECLARE_NAPI_FUNCTION("startBackupEx", JSStartBackupEx),
74         DECLARE_NAPI_FUNCTION("release", JSRelease),
75     };
76 
77     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(media_library_properties) /
78         sizeof(media_library_properties[0]), media_library_properties));
79     return exports;
80 }
81 
GetIntFromParams(napi_env env,const napi_value args[],size_t index)82 static int32_t GetIntFromParams(napi_env env, const napi_value args[], size_t index)
83 {
84     int32_t result = -1;
85     napi_valuetype valueType = napi_undefined;
86     if (napi_typeof(env, args[index], &valueType) != napi_ok || valueType != napi_number) {
87         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
88         return result;
89     }
90     napi_get_value_int32(env, args[index], &result);
91     return result;
92 }
93 
GetStringFromParams(napi_env env,const napi_value args[],size_t index)94 static std::string GetStringFromParams(napi_env env, const napi_value args[], size_t index)
95 {
96     napi_valuetype valueType = napi_undefined;
97     if (napi_typeof(env, args[index], &valueType) != napi_ok || valueType != napi_string) {
98         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
99         return "";
100     }
101 
102     size_t resultLength;
103     napi_get_value_string_utf8(env, args[index], nullptr, 0, &resultLength);
104     std::string result(resultLength, '\0');
105     napi_get_value_string_utf8(env, args[index], &result[0], resultLength + 1, &resultLength);
106     return result;
107 }
108 
CheckPermission(void)109 static int32_t CheckPermission(void)
110 {
111     auto context = AbilityRuntime::Context::GetApplicationContext();
112     if (context == nullptr) {
113         NAPI_ERR_LOG("Failed to get context");
114         return E_FAIL;
115     }
116     std::string bundleName = context->GetBundleName();
117     if (bundleName.compare(BUNDLE_NAME) != 0) {
118         NAPI_ERR_LOG("bundleName is invalid, %{public}s", bundleName.c_str());
119         return E_FAIL;
120     }
121     return E_OK;
122 }
123 
UvQueueWork(uv_loop_s * loop,uv_work_t * work)124 void MediaLibraryBackupNapi::UvQueueWork(uv_loop_s *loop, uv_work_t *work)
125 {
126     uv_queue_work(loop, work, [](uv_work_t *work) {
127         RestoreBlock *block = reinterpret_cast<RestoreBlock *> (work->data);
128         if (block == nullptr) {
129             delete work;
130             return;
131         }
132         BackupRestoreService::GetInstance().StartRestore(block->context.lock(), block->restoreInfo);
133     }, [](uv_work_t *work, int _status) {
134         RestoreBlock *block = reinterpret_cast<RestoreBlock *> (work->data);
135         napi_handle_scope scope = nullptr;
136         napi_open_handle_scope(block->env, &scope);
137         if (scope == nullptr) {
138             delete work;
139             return;
140         }
141         napi_value resultCode = nullptr;
142         napi_create_int32(block->env, 1, &resultCode);
143         napi_resolve_deferred(block->env, block->nativeDeferred, resultCode);
144         napi_close_handle_scope(block->env, scope);
145         delete block;
146         delete work;
147     });
148 }
149 
ParseContext(const napi_env & env,const napi_value & input,std::shared_ptr<OHOS::AbilityRuntime::Context> & context)150 bool ParseContext(const napi_env &env, const napi_value &input,
151     std::shared_ptr<OHOS::AbilityRuntime::Context> &context)
152 {
153     bool isStageMode = false;
154     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, input, isStageMode);
155     if (status != napi_ok) {
156         NAPI_ERR_LOG("parse context status error, status:%{public}d", status);
157         return false;
158     }
159     if (!isStageMode) {
160         NAPI_ERR_LOG("parse context failed, not stage context");
161         return false;
162     }
163     context = OHOS::AbilityRuntime::GetStageModeContext(env, input);
164     if (context == nullptr) {
165         NAPI_ERR_LOG("parse context failed, context is null");
166         return false;
167     }
168 
169     return true;
170 }
171 
JSStartRestore(napi_env env,napi_callback_info info)172 napi_value MediaLibraryBackupNapi::JSStartRestore(napi_env env, napi_callback_info info)
173 {
174     napi_value result = nullptr;
175     if (CheckPermission() != E_OK) {
176         return result;
177     }
178 
179     size_t argc = ARGS_FIVE;
180     napi_value argv[ARGS_FIVE] = {0};
181     napi_value thisVar = nullptr;
182 
183     GET_JS_ARGS(env, info, argc, argv, thisVar);
184     NAPI_ASSERT(env, (argc == ARGS_FIVE), "requires 5 parameters");
185     napi_get_undefined(env, &result);
186 
187     // get ability context
188     std::shared_ptr<OHOS::AbilityRuntime::Context> context;
189     if (!ParseContext(env, argv[PARAM0], context)) {
190         return result;
191     }
192     RestoreInfo restoreInfo;
193     restoreInfo.sceneCode = GetIntFromParams(env, argv, PARAM1);
194     restoreInfo.galleryAppName = GetStringFromParams(env, argv, PARAM2);
195     restoreInfo.mediaAppName = GetStringFromParams(env, argv, PARAM3);
196     restoreInfo.backupDir = GetStringFromParams(env, argv, PARAM4);
197     NAPI_INFO_LOG("StartRestore, sceneCode = %{public}d", restoreInfo.sceneCode);
198 
199     if (restoreInfo.sceneCode < 0) {
200         NAPI_ERR_LOG("Parameters error, sceneCode = %{public}d", restoreInfo.sceneCode);
201         return result;
202     }
203     uv_loop_s *loop = nullptr;
204     napi_get_uv_event_loop(env, &loop);
205     uv_work_t *work = new (std::nothrow) uv_work_t;
206     if (work == nullptr) {
207         NAPI_ERR_LOG("Failed to new uv_work");
208         return result;
209     }
210     napi_deferred nativeDeferred = nullptr;
211     napi_create_promise(env, &nativeDeferred, &result);
212     RestoreBlock *block = new (std::nothrow) RestoreBlock { env, context, restoreInfo, nativeDeferred };
213     if (block == nullptr) {
214         NAPI_ERR_LOG("Failed to new block");
215         delete work;
216         return result;
217     }
218     work->data = reinterpret_cast<void *>(block);
219     UvQueueWork(loop, work);
220     return result;
221 }
222 
UvQueueWorkEx(uv_loop_s * loop,uv_work_t * work)223 void MediaLibraryBackupNapi::UvQueueWorkEx(uv_loop_s *loop, uv_work_t *work)
224 {
225     uv_queue_work(loop, work, [](uv_work_t *work) {
226         RestoreExBlock *block = reinterpret_cast<RestoreExBlock *> (work->data);
227         BackupRestoreService::GetInstance().StartRestoreEx(block->context.lock(), block->restoreInfo,
228             block->restoreExInfo);
229     }, [](uv_work_t *work, int _status) {
230         RestoreExBlock *block = reinterpret_cast<RestoreExBlock *> (work->data);
231         if (block == nullptr) {
232             delete work;
233             return;
234         }
235         napi_handle_scope scope = nullptr;
236         napi_open_handle_scope(block->env, &scope);
237         if (scope == nullptr) {
238             delete work;
239             return;
240         }
241         napi_value restoreExResult = nullptr;
242         napi_create_string_utf8(block->env, block->restoreExInfo.c_str(), NAPI_AUTO_LENGTH, &restoreExResult);
243         napi_resolve_deferred(block->env, block->nativeDeferred, restoreExResult);
244         napi_close_handle_scope(block->env, scope);
245         delete block;
246         delete work;
247     });
248 }
249 
JSStartRestoreEx(napi_env env,napi_callback_info info)250 napi_value MediaLibraryBackupNapi::JSStartRestoreEx(napi_env env, napi_callback_info info)
251 {
252     napi_value result = nullptr;
253     if (CheckPermission() != E_OK) {
254         return result;
255     }
256 
257     size_t argc = ARGS_SIX;
258     napi_value argv[ARGS_SIX] = {0};
259     napi_value thisVar = nullptr;
260 
261     GET_JS_ARGS(env, info, argc, argv, thisVar);
262     NAPI_ASSERT(env, (argc == ARGS_SIX), "requires 6 parameters");
263     napi_get_undefined(env, &result);
264     // get ability context
265     std::shared_ptr<OHOS::AbilityRuntime::Context> context;
266     if (!ParseContext(env, argv[PARAM0], context)) {
267         return result;
268     }
269     RestoreInfo restoreInfo;
270     restoreInfo.sceneCode = GetIntFromParams(env, argv, PARAM1);
271     restoreInfo.galleryAppName = GetStringFromParams(env, argv, PARAM2);
272     restoreInfo.mediaAppName = GetStringFromParams(env, argv, PARAM3);
273     restoreInfo.backupDir = GetStringFromParams(env, argv, PARAM4);
274     restoreInfo.bundleInfo = GetStringFromParams(env, argv, PARAM5);
275     std::string restoreExInfo;
276     NAPI_INFO_LOG("StartRestoreEx, sceneCode = %{public}d", restoreInfo.sceneCode);
277     if (restoreInfo.sceneCode < 0) {
278         NAPI_INFO_LOG("Parameters error, sceneCode = %{public}d", restoreInfo.sceneCode);
279         return result;
280     }
281     uv_loop_s *loop = nullptr;
282     napi_get_uv_event_loop(env, &loop);
283     uv_work_t *work = new (std::nothrow) uv_work_t;
284     if (work == nullptr) {
285         NAPI_ERR_LOG("Failed to new uv_work");
286         return result;
287     }
288     napi_deferred nativeDeferred = nullptr;
289     napi_create_promise(env, &nativeDeferred, &result);
290     RestoreExBlock *block = new (std::nothrow) RestoreExBlock {
291         env, context, restoreInfo, restoreExInfo, nativeDeferred };
292     if (block == nullptr) {
293         NAPI_ERR_LOG("Failed to new block");
294         delete work;
295         return result;
296     }
297     work->data = reinterpret_cast<void *>(block);
298     UvQueueWorkEx(loop, work);
299     return result;
300 }
301 
JSGetBackupInfo(napi_env env,napi_callback_info info)302 napi_value MediaLibraryBackupNapi::JSGetBackupInfo(napi_env env, napi_callback_info info)
303 {
304     napi_value result = nullptr;
305     if (CheckPermission() != E_OK) {
306         return result;
307     }
308 
309     size_t argc = ARGS_ONE;
310     napi_value argv[ARGS_ONE] = {0};
311     napi_value thisVar = nullptr;
312 
313     GET_JS_ARGS(env, info, argc, argv, thisVar);
314     NAPI_ASSERT(env, (argc == ARGS_ONE), "requires 1 parameters");
315     napi_get_undefined(env, &result);
316     int32_t sceneCode = GetIntFromParams(env, argv, PARAM0);
317     NAPI_INFO_LOG("GetBackupInfo, sceneCode = %{public}d", sceneCode);
318     if (sceneCode < 0) {
319         NAPI_INFO_LOG("Parameters error, sceneCode = %{public}d", sceneCode);
320         return result;
321     }
322     std::string backupInfo;
323     BackupRestoreService::GetInstance().GetBackupInfo(sceneCode, backupInfo);
324     CHECK_ARGS(env, napi_create_string_utf8(env, backupInfo.c_str(), NAPI_AUTO_LENGTH, &result), JS_INNER_FAIL);
325     return result;
326 }
327 
JSGetProgressInfo(napi_env env,napi_callback_info info)328 napi_value MediaLibraryBackupNapi::JSGetProgressInfo(napi_env env, napi_callback_info info)
329 {
330     napi_value result = nullptr;
331     if (CheckPermission() != E_OK) {
332         return result;
333     }
334 
335     std::string progressInfo;
336     BackupRestoreService::GetInstance().GetProgressInfo(progressInfo);
337     CHECK_ARGS(env, napi_create_string_utf8(env, progressInfo.c_str(), NAPI_AUTO_LENGTH, &result), JS_INNER_FAIL);
338     return result;
339 }
340 
UvBackupWork(uv_loop_s * loop,uv_work_t * work)341 void MediaLibraryBackupNapi::UvBackupWork(uv_loop_s *loop, uv_work_t *work)
342 {
343     uv_queue_work(loop, work, [](uv_work_t *work) {
344         BackupBlock *block = reinterpret_cast<BackupBlock *> (work->data);
345         BackupRestoreService::GetInstance().StartBackup(block->sceneCode, block->galleryAppName,
346             block->mediaAppName);
347     }, [](uv_work_t *work, int _status) {
348         BackupBlock *block = reinterpret_cast<BackupBlock *> (work->data);
349         if (block == nullptr) {
350             delete work;
351             return;
352         }
353         napi_handle_scope scope = nullptr;
354         napi_open_handle_scope(block->env, &scope);
355         if (scope == nullptr) {
356             delete work;
357             return;
358         }
359         napi_value resultCode = nullptr;
360         napi_create_int32(block->env, 1, &resultCode);
361         napi_resolve_deferred(block->env, block->nativeDeferred, resultCode);
362         napi_close_handle_scope(block->env, scope);
363         delete block;
364         delete work;
365     });
366 }
367 
JSStartBackup(napi_env env,napi_callback_info info)368 napi_value MediaLibraryBackupNapi::JSStartBackup(napi_env env, napi_callback_info info)
369 {
370     napi_value result = nullptr;
371     if (CheckPermission() != E_OK) {
372         return result;
373     }
374 
375     size_t argc = ARGS_THREE;
376     napi_value argv[ARGS_THREE] = {0};
377     napi_value thisVar = nullptr;
378 
379     GET_JS_ARGS(env, info, argc, argv, thisVar);
380     NAPI_ASSERT(env, (argc == ARGS_THREE), "requires 3 parameters");
381     napi_get_undefined(env, &result);
382     int32_t sceneCode = GetIntFromParams(env, argv, PARAM0);
383     std::string galleryAppName = GetStringFromParams(env, argv, PARAM1);
384     std::string mediaAppName = GetStringFromParams(env, argv, PARAM2);
385     NAPI_INFO_LOG("StartBackup, sceneCode = %{public}d", sceneCode);
386     if (sceneCode < 0) {
387         NAPI_INFO_LOG("Parameters error, sceneCode = %{public}d", sceneCode);
388         return result;
389     }
390     uv_loop_s *loop = nullptr;
391     napi_get_uv_event_loop(env, &loop);
392     uv_work_t *work = new (std::nothrow) uv_work_t;
393     if (work == nullptr) {
394         NAPI_ERR_LOG("Failed to new uv_work");
395         return result;
396     }
397     napi_deferred nativeDeferred = nullptr;
398     napi_create_promise(env, &nativeDeferred, &result);
399     BackupBlock *block = new (std::nothrow) BackupBlock {
400         env, sceneCode, galleryAppName, mediaAppName, nativeDeferred };
401     if (block == nullptr) {
402         NAPI_ERR_LOG("Failed to new block");
403         delete work;
404         return result;
405     }
406     work->data = reinterpret_cast<void *>(block);
407     UvBackupWork(loop, work);
408     return result;
409 }
410 
JSStartBackupEx(napi_env env,napi_callback_info info)411 napi_value MediaLibraryBackupNapi::JSStartBackupEx(napi_env env, napi_callback_info info)
412 {
413     napi_value result = nullptr;
414     if (CheckPermission() != E_OK) {
415         return result;
416     }
417 
418     size_t argc = ARGS_FOUR;
419     napi_value argv[ARGS_FOUR] = {0};
420     napi_value thisVar = nullptr;
421 
422     GET_JS_ARGS(env, info, argc, argv, thisVar);
423     NAPI_ASSERT(env, (argc == ARGS_FOUR), "requires 4 parameters");
424     napi_get_undefined(env, &result);
425     int32_t sceneCode = GetIntFromParams(env, argv, PARAM0);
426     std::string galleryAppName = GetStringFromParams(env, argv, PARAM1);
427     std::string mediaAppName = GetStringFromParams(env, argv, PARAM2);
428     std::string backupInfo = GetStringFromParams(env, argv, PARAM3);
429     std::string backupExInfo;
430     NAPI_INFO_LOG("StartBackup, sceneCode = %{public}d", sceneCode);
431     if (sceneCode < 0) {
432         NAPI_INFO_LOG("Parameters error, sceneCode = %{public}d", sceneCode);
433         return result;
434     }
435     uv_loop_s *loop = nullptr;
436     napi_get_uv_event_loop(env, &loop);
437     uv_work_t *work = new (std::nothrow) uv_work_t;
438     if (work == nullptr) {
439         NAPI_ERR_LOG("Failed to new uv_work");
440         return result;
441     }
442     napi_deferred nativeDeferred = nullptr;
443     napi_create_promise(env, &nativeDeferred, &result);
444     BackupExBlock *block = new (std::nothrow) BackupExBlock {
445         env, sceneCode, galleryAppName, mediaAppName, nativeDeferred, backupInfo, backupExInfo };
446     if (block == nullptr) {
447         NAPI_ERR_LOG("Failed to new block");
448         delete work;
449         return result;
450     }
451     work->data = reinterpret_cast<void *>(block);
452     UvBackupWorkEx(loop, work);
453     return result;
454 }
455 
UvBackupWorkEx(uv_loop_s * loop,uv_work_t * work)456 void MediaLibraryBackupNapi::UvBackupWorkEx(uv_loop_s *loop, uv_work_t *work)
457 {
458     uv_queue_work(loop, work, [](uv_work_t *work) {
459         BackupExBlock *block = reinterpret_cast<BackupExBlock *> (work->data);
460         BackupRestoreService::GetInstance().StartBackupEx(block->sceneCode, block->galleryAppName,
461             block->mediaAppName, block->backupInfo, block->backupExInfo);
462     }, [](uv_work_t *work, int _status) {
463         BackupExBlock *block = reinterpret_cast<BackupExBlock *> (work->data);
464         if (block == nullptr) {
465             delete work;
466             return;
467         }
468         napi_handle_scope scope = nullptr;
469         napi_open_handle_scope(block->env, &scope);
470         if (scope == nullptr) {
471             delete work;
472             return;
473         }
474         napi_value napiBackupExResult = nullptr;
475         napi_create_string_utf8(block->env, block->backupExInfo.c_str(), NAPI_AUTO_LENGTH, &napiBackupExResult);
476         napi_resolve_deferred(block->env, block->nativeDeferred, napiBackupExResult);
477         napi_close_handle_scope(block->env, scope);
478         delete block;
479         delete work;
480     });
481 }
482 
JSRelease(napi_env env,napi_callback_info info)483 napi_value MediaLibraryBackupNapi::JSRelease(napi_env env, napi_callback_info info)
484 {
485     napi_value result = nullptr;
486     if (CheckPermission() != E_OK) {
487         return result;
488     }
489 
490     size_t argc = ARGS_TWO;
491     napi_value argv[ARGS_TWO] = {0};
492     napi_value thisVar = nullptr;
493 
494     GET_JS_ARGS(env, info, argc, argv, thisVar);
495     NAPI_ASSERT(env, (argc == ARGS_TWO), "requires 2 parameters");
496     napi_get_undefined(env, &result);
497     int32_t sceneCode = GetIntFromParams(env, argv, PARAM0);
498     int32_t releaseScene = GetIntFromParams(env, argv, PARAM1);
499     NAPI_INFO_LOG("Release, sceneCode:%{public}d releaseScene = %{public}d", sceneCode, releaseScene);
500     BackupRestoreService::GetInstance().Release(sceneCode, releaseScene);
501     return result;
502 }
503 } // namespace Media
504 } // namespace OHOS
505