• 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 
Init(napi_env env,napi_value exports)46 napi_value MediaLibraryBackupNapi::Init(napi_env env, napi_value exports)
47 {
48     NAPI_INFO_LOG("Init, MediaLibraryBackupNapi has been used.");
49     napi_property_descriptor media_library_properties[] = {
50         DECLARE_NAPI_FUNCTION("startRestore", JSStartRestore),
51         DECLARE_NAPI_FUNCTION("startRestoreEx", JSStartRestoreEx),
52         DECLARE_NAPI_FUNCTION("getBackupInfo", JSGetBackupInfo),
53         DECLARE_NAPI_FUNCTION("getProgressInfo", JSGetProgressInfo),
54     };
55 
56     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(media_library_properties) /
57         sizeof(media_library_properties[0]), media_library_properties));
58     return exports;
59 }
60 
GetIntFromParams(napi_env env,const napi_value args[],size_t index)61 static int32_t GetIntFromParams(napi_env env, const napi_value args[], size_t index)
62 {
63     int32_t result = -1;
64     napi_valuetype valueType = napi_undefined;
65     if (napi_typeof(env, args[index], &valueType) != napi_ok || valueType != napi_number) {
66         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
67         return result;
68     }
69     napi_get_value_int32(env, args[index], &result);
70     return result;
71 }
72 
GetStringFromParams(napi_env env,const napi_value args[],size_t index)73 static std::string GetStringFromParams(napi_env env, const napi_value args[], size_t index)
74 {
75     napi_valuetype valueType = napi_undefined;
76     if (napi_typeof(env, args[index], &valueType) != napi_ok || valueType != napi_string) {
77         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID);
78         return "";
79     }
80 
81     size_t resultLength;
82     napi_get_value_string_utf8(env, args[index], nullptr, 0, &resultLength);
83     std::string result(resultLength, '\0');
84     napi_get_value_string_utf8(env, args[index], &result[0], resultLength + 1, &resultLength);
85     return result;
86 }
87 
CheckPermission(void)88 static int32_t CheckPermission(void)
89 {
90     auto context = AbilityRuntime::Context::GetApplicationContext();
91     if (context == nullptr) {
92         NAPI_ERR_LOG("Failed to get context");
93         return E_FAIL;
94     }
95     std::string bundleName = context->GetBundleName();
96     if (bundleName.compare(BUNDLE_NAME) != 0) {
97         NAPI_ERR_LOG("bundleName is invalid, %{public}s", bundleName.c_str());
98         return E_FAIL;
99     }
100     return E_OK;
101 }
102 
UvQueueWork(uv_loop_s * loop,uv_work_t * work)103 void MediaLibraryBackupNapi::UvQueueWork(uv_loop_s *loop, uv_work_t *work)
104 {
105     uv_queue_work(loop, work, [](uv_work_t *work) {
106         RestoreBlock *block = reinterpret_cast<RestoreBlock *> (work->data);
107         if (block == nullptr) {
108             delete work;
109             return;
110         }
111         BackupRestoreService::GetInstance().StartRestore(block->context.lock(), block->restoreInfo);
112     }, [](uv_work_t *work, int _status) {
113         RestoreBlock *block = reinterpret_cast<RestoreBlock *> (work->data);
114         napi_handle_scope scope = nullptr;
115         napi_open_handle_scope(block->env, &scope);
116         if (scope == nullptr) {
117             delete work;
118             return;
119         }
120         napi_value resultCode = nullptr;
121         napi_create_int32(block->env, 1, &resultCode);
122         napi_resolve_deferred(block->env, block->nativeDeferred, resultCode);
123         napi_close_handle_scope(block->env, scope);
124         delete block;
125         delete work;
126     });
127 }
128 
ParseContext(const napi_env & env,const napi_value & input,std::shared_ptr<OHOS::AbilityRuntime::Context> & context)129 bool ParseContext(const napi_env &env, const napi_value &input,
130     std::shared_ptr<OHOS::AbilityRuntime::Context> &context)
131 {
132     bool isStageMode = false;
133     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, input, isStageMode);
134     if (status != napi_ok) {
135         NAPI_ERR_LOG("parse context status error, status:%{public}d", status);
136         return false;
137     }
138     if (!isStageMode) {
139         NAPI_ERR_LOG("parse context failed, not stage context");
140         return false;
141     }
142     context = OHOS::AbilityRuntime::GetStageModeContext(env, input);
143     if (context == nullptr) {
144         NAPI_ERR_LOG("parse context failed, context is null");
145         return false;
146     }
147 
148     return true;
149 }
150 
JSStartRestore(napi_env env,napi_callback_info info)151 napi_value MediaLibraryBackupNapi::JSStartRestore(napi_env env, napi_callback_info info)
152 {
153     napi_value result = nullptr;
154     if (CheckPermission() != E_OK) {
155         return result;
156     }
157 
158     size_t argc = ARGS_FIVE;
159     napi_value argv[ARGS_FIVE] = {0};
160     napi_value thisVar = nullptr;
161 
162     GET_JS_ARGS(env, info, argc, argv, thisVar);
163     NAPI_ASSERT(env, (argc == ARGS_FIVE), "requires 5 parameters");
164     napi_get_undefined(env, &result);
165 
166     // get ability context
167     std::shared_ptr<OHOS::AbilityRuntime::Context> context;
168     if (!ParseContext(env, argv[PARAM0], context)) {
169         return result;
170     }
171     RestoreInfo restoreInfo;
172     restoreInfo.sceneCode = GetIntFromParams(env, argv, PARAM1);
173     restoreInfo.galleryAppName = GetStringFromParams(env, argv, PARAM2);
174     restoreInfo.mediaAppName = GetStringFromParams(env, argv, PARAM3);
175     restoreInfo.backupDir = GetStringFromParams(env, argv, PARAM4);
176     NAPI_INFO_LOG("StartRestore, sceneCode = %{public}d", restoreInfo.sceneCode);
177 
178     if (restoreInfo.sceneCode < 0) {
179         NAPI_ERR_LOG("Parameters error, sceneCode = %{public}d", restoreInfo.sceneCode);
180         return result;
181     }
182     uv_loop_s *loop = nullptr;
183     napi_get_uv_event_loop(env, &loop);
184     uv_work_t *work = new (std::nothrow) uv_work_t;
185     if (work == nullptr) {
186         NAPI_ERR_LOG("Failed to new uv_work");
187         return result;
188     }
189     napi_deferred nativeDeferred = nullptr;
190     napi_create_promise(env, &nativeDeferred, &result);
191     RestoreBlock *block = new (std::nothrow) RestoreBlock { env, context, restoreInfo, nativeDeferred };
192     if (block == nullptr) {
193         NAPI_ERR_LOG("Failed to new block");
194         delete work;
195         return result;
196     }
197     work->data = reinterpret_cast<void *>(block);
198     UvQueueWork(loop, work);
199     return result;
200 }
201 
UvQueueWorkEx(uv_loop_s * loop,uv_work_t * work)202 void MediaLibraryBackupNapi::UvQueueWorkEx(uv_loop_s *loop, uv_work_t *work)
203 {
204     uv_queue_work(loop, work, [](uv_work_t *work) {
205         RestoreExBlock *block = reinterpret_cast<RestoreExBlock *> (work->data);
206         BackupRestoreService::GetInstance().StartRestoreEx(block->context.lock(), block->restoreInfo,
207             block->restoreExInfo);
208     }, [](uv_work_t *work, int _status) {
209         RestoreExBlock *block = reinterpret_cast<RestoreExBlock *> (work->data);
210         if (block == nullptr) {
211             delete work;
212             return;
213         }
214         napi_handle_scope scope = nullptr;
215         napi_open_handle_scope(block->env, &scope);
216         if (scope == nullptr) {
217             delete work;
218             return;
219         }
220         napi_value restoreExResult = nullptr;
221         napi_create_string_utf8(block->env, block->restoreExInfo.c_str(), NAPI_AUTO_LENGTH, &restoreExResult);
222         napi_resolve_deferred(block->env, block->nativeDeferred, restoreExResult);
223         napi_close_handle_scope(block->env, scope);
224         delete block;
225         delete work;
226     });
227 }
228 
JSStartRestoreEx(napi_env env,napi_callback_info info)229 napi_value MediaLibraryBackupNapi::JSStartRestoreEx(napi_env env, napi_callback_info info)
230 {
231     napi_value result = nullptr;
232     if (CheckPermission() != E_OK) {
233         return result;
234     }
235 
236     size_t argc = ARGS_SIX;
237     napi_value argv[ARGS_SIX] = {0};
238     napi_value thisVar = nullptr;
239 
240     GET_JS_ARGS(env, info, argc, argv, thisVar);
241     NAPI_ASSERT(env, (argc == ARGS_SIX), "requires 6 parameters");
242     napi_get_undefined(env, &result);
243     // get ability context
244     std::shared_ptr<OHOS::AbilityRuntime::Context> context;
245     if (!ParseContext(env, argv[PARAM0], context)) {
246         return result;
247     }
248     RestoreInfo restoreInfo;
249     restoreInfo.sceneCode = GetIntFromParams(env, argv, PARAM1);
250     restoreInfo.galleryAppName = GetStringFromParams(env, argv, PARAM2);
251     restoreInfo.mediaAppName = GetStringFromParams(env, argv, PARAM3);
252     restoreInfo.backupDir = GetStringFromParams(env, argv, PARAM4);
253     restoreInfo.bundleInfo = GetStringFromParams(env, argv, PARAM5);
254     std::string restoreExInfo;
255     NAPI_INFO_LOG("StartRestoreEx, sceneCode = %{public}d", restoreInfo.sceneCode);
256     if (restoreInfo.sceneCode < 0) {
257         NAPI_INFO_LOG("Parameters error, sceneCode = %{public}d", restoreInfo.sceneCode);
258         return result;
259     }
260     uv_loop_s *loop = nullptr;
261     napi_get_uv_event_loop(env, &loop);
262     uv_work_t *work = new (std::nothrow) uv_work_t;
263     if (work == nullptr) {
264         NAPI_ERR_LOG("Failed to new uv_work");
265         return result;
266     }
267     napi_deferred nativeDeferred = nullptr;
268     napi_create_promise(env, &nativeDeferred, &result);
269     RestoreExBlock *block = new (std::nothrow) RestoreExBlock {
270         env, context, restoreInfo, restoreExInfo, nativeDeferred };
271     if (block == nullptr) {
272         NAPI_ERR_LOG("Failed to new block");
273         delete work;
274         return result;
275     }
276     work->data = reinterpret_cast<void *>(block);
277     UvQueueWorkEx(loop, work);
278     return result;
279 }
280 
JSGetBackupInfo(napi_env env,napi_callback_info info)281 napi_value MediaLibraryBackupNapi::JSGetBackupInfo(napi_env env, napi_callback_info info)
282 {
283     napi_value result = nullptr;
284     if (CheckPermission() != E_OK) {
285         return result;
286     }
287 
288     size_t argc = ARGS_ONE;
289     napi_value argv[ARGS_ONE] = {0};
290     napi_value thisVar = nullptr;
291 
292     GET_JS_ARGS(env, info, argc, argv, thisVar);
293     NAPI_ASSERT(env, (argc == ARGS_ONE), "requires 1 parameters");
294     napi_get_undefined(env, &result);
295     int32_t sceneCode = GetIntFromParams(env, argv, PARAM0);
296     NAPI_INFO_LOG("GetBackupInfo, sceneCode = %{public}d", sceneCode);
297     if (sceneCode < 0) {
298         NAPI_INFO_LOG("Parameters error, sceneCode = %{public}d", sceneCode);
299         return result;
300     }
301     std::string backupInfo;
302     BackupRestoreService::GetInstance().GetBackupInfo(sceneCode, backupInfo);
303     CHECK_ARGS(env, napi_create_string_utf8(env, backupInfo.c_str(), NAPI_AUTO_LENGTH, &result), JS_INNER_FAIL);
304     return result;
305 }
306 
JSGetProgressInfo(napi_env env,napi_callback_info info)307 napi_value MediaLibraryBackupNapi::JSGetProgressInfo(napi_env env, napi_callback_info info)
308 {
309     napi_value result = nullptr;
310     if (CheckPermission() != E_OK) {
311         return result;
312     }
313 
314     std::string progressInfo;
315     BackupRestoreService::GetInstance().GetProgressInfo(progressInfo);
316     CHECK_ARGS(env, napi_create_string_utf8(env, progressInfo.c_str(), NAPI_AUTO_LENGTH, &result), JS_INNER_FAIL);
317     return result;
318 }
319 } // namespace Media
320 } // namespace OHOS
321