• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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 #include "session_backup_n_exporter.h"
16 
17 #include <functional>
18 #include <memory>
19 
20 #include "b_error/b_error.h"
21 #include "b_filesystem/b_file.h"
22 #include "b_resources/b_constants.h"
23 #include "b_sa/b_sa_utils.h"
24 #include "b_session_backup.h"
25 #include "backup_kit_inner.h"
26 #include "directory_ex.h"
27 #include "filemgmt_libhilog.h"
28 #include "general_callbacks.h"
29 #include "parse_inc_info_from_js.h"
30 #include "service_proxy.h"
31 
32 namespace OHOS::FileManagement::Backup {
33 using namespace std;
34 using namespace LibN;
35 
36 struct BackupEntity {
37     unique_ptr<BSessionBackup> session;
38     shared_ptr<GeneralCallbacks> callbacks;
39 };
40 
OnFileReady(weak_ptr<GeneralCallbacks> pCallbacks,const BFileInfo & fileInfo,UniqueFd fd,int sysErrno)41 static void OnFileReady(weak_ptr<GeneralCallbacks> pCallbacks, const BFileInfo &fileInfo, UniqueFd fd, int sysErrno)
42 {
43     auto callbacks = pCallbacks.lock();
44     if (!callbacks) {
45         HILOGI("callback function onFileReady has already been released");
46         return;
47     }
48     if (!bool(callbacks->onFileReady)) {
49         HILOGI("callback function onFileReady is undefined");
50         return;
51     }
52     ErrCode errCode = BError::GetCodeByErrno(sysErrno);
53     std::string errMsg = "system errno: " + to_string(sysErrno);
54     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
55     HILOGI("callback function backup onFileReady begin errCode: %{public}d, bundle: %{public}s, file: %{public}s",
56         std::get<0>(errInfo), fileInfo.owner.c_str(), GetAnonyPath(fileInfo.fileName).c_str());
57     auto cbCompl = [bundleName {fileInfo.owner}, fileName {fileInfo.fileName},
58                     fd {make_shared<UniqueFd>(fd.Release())}, errInfo](napi_env env, NError err) -> NVal {
59         if (err) {
60             return {env, err.GetNapiErr(env)};
61         }
62         HILOGI("callback function backup onFileReady errCode: %{public}d, bundle: %{public}s, file: %{public}s",
63             std::get<0>(errInfo), bundleName.c_str(), GetAnonyPath(fileName).c_str());
64         NVal obj;
65         ErrParam errorParam = [ errInfo ]() {
66             return errInfo;
67         };
68         if (std::get<0>(errInfo) != 0) {
69             obj = NVal {env, NError(errorParam).GetNapiErr(env)};
70             napi_status status = napi_set_named_property(env, obj.val_, FILEIO_TAG_ERR_DATA.c_str(),
71                 NVal::CreateUTF8String(env, bundleName).val_);
72             if (status != napi_ok) {
73                 HILOGE("Failed to set data property, status %{public}d, bundleName %{public}s",
74                     status, bundleName.c_str());
75             }
76         } else {
77             obj = NVal::CreateObject(env);
78             obj.AddProp({
79                 NVal::DeclareNapiProperty(BConstants::BUNDLE_NAME.c_str(),
80                     NVal::CreateUTF8String(env, bundleName).val_),
81                 NVal::DeclareNapiProperty(BConstants::URI.c_str(), NVal::CreateUTF8String(env, fileName).val_),
82                 NVal::DeclareNapiProperty(BConstants::FD.c_str(), NVal::CreateInt32(env, fd->Release()).val_)});
83         }
84         HILOGI("callback function backup onFileReady end errCode: %{public}d, bundle: %{public}s, file: %{public}s",
85             std::get<0>(errInfo), bundleName.c_str(), GetAnonyPath(fileName).c_str());
86         return {obj};
87     };
88 
89     callbacks->onFileReady.ThreadSafeSchedule(cbCompl);
90 }
91 
onBundleBegin(weak_ptr<GeneralCallbacks> pCallbacks,ErrCode err,const BundleName name)92 static void onBundleBegin(weak_ptr<GeneralCallbacks> pCallbacks, ErrCode err, const BundleName name)
93 {
94     HILOGI("Callback onBundleBegin, bundleName=%{public}s, errCode=%{public}d", name.c_str(), err);
95     auto callbacks = pCallbacks.lock();
96     if (!callbacks) {
97         HILOGI("callback function onBundleBegin has already been released");
98         return;
99     }
100     if (!bool(callbacks->onBundleBegin)) {
101         HILOGI("callback function onBundleBegin is undefined");
102         return;
103     }
104 
105     ErrCode errCode = BError::GetBackupCodeByErrno(err);
106     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
107     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
108     HILOGI("callback function backup onBundleBegin start errCode: %{public}d", std::get<0>(errInfo));
109     auto cbCompl = [name {name}, errCode {err}, errInfo](napi_env env, NError err) -> NVal {
110         NVal bundleName = NVal::CreateUTF8String(env, name);
111         if (!err && errCode == 0) {
112             return bundleName;
113         }
114         ErrParam errorParam = [ errInfo ]() {
115             return errInfo;
116         };
117         NVal res;
118         if (err) {
119             res = NVal {env, err.GetNapiErr(env)};
120         } else {
121             res = NVal {env, NError(errorParam).GetNapiErr(env)};
122         }
123         napi_status status = napi_set_named_property(env, res.val_, FILEIO_TAG_ERR_DATA.c_str(), bundleName.val_);
124         if (status != napi_ok) {
125             HILOGE("Failed to set data property, status %{public}d, bundleName %{public}s", status, name.c_str());
126         }
127         HILOGI("callback function backup onBundleBegin end errCode: %{public}d", std::get<0>(errInfo));
128         return res;
129     };
130 
131     callbacks->onBundleBegin.ThreadSafeSchedule(cbCompl);
132 }
133 
onBundleEnd(weak_ptr<GeneralCallbacks> pCallbacks,ErrCode err,const BundleName name)134 static void onBundleEnd(weak_ptr<GeneralCallbacks> pCallbacks, ErrCode err, const BundleName name)
135 {
136     HILOGI("Callback onBundleEnd, bundleName=%{public}s, errCode=%{public}d", name.c_str(), err);
137     auto callbacks = pCallbacks.lock();
138     if (!callbacks) {
139         HILOGI("callback function onBundleEnd has already been released");
140         return;
141     }
142     if (!bool(callbacks->onBundleEnd)) {
143         HILOGI("callback function onBundleEnd is undefined");
144         return;
145     }
146 
147     ErrCode errCode = BError::GetBackupCodeByErrno(err);
148     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
149     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
150     HILOGI("callback function backup onBundleEnd start errCode: %{public}d", std::get<0>(errInfo));
151     auto cbCompl = [name {name}, errCode {err}, errInfo](napi_env env, NError err) -> NVal {
152         NVal bundleName = NVal::CreateUTF8String(env, name);
153         if (!err && errCode == 0) {
154             return bundleName;
155         }
156         ErrParam errorParam = [ errInfo ]() {
157             return errInfo;
158         };
159         NVal res;
160         if (err) {
161             res = NVal {env, err.GetNapiErr(env)};
162         } else {
163             res = NVal {env, NError(errorParam).GetNapiErr(env)};
164         }
165         napi_status status = napi_set_named_property(env, res.val_, FILEIO_TAG_ERR_DATA.c_str(), bundleName.val_);
166         if (status != napi_ok) {
167             HILOGE("Failed to set data property, status %{public}d, bundleName %{public}s", status, name.c_str());
168         }
169         HILOGI("callback function backup onBundleEnd end errCode: %{public}d", std::get<0>(errInfo));
170         return res;
171     };
172 
173     callbacks->onBundleEnd.ThreadSafeSchedule(cbCompl);
174 }
175 
onAllBundlesEnd(weak_ptr<GeneralCallbacks> pCallbacks,ErrCode err)176 static void onAllBundlesEnd(weak_ptr<GeneralCallbacks> pCallbacks, ErrCode err)
177 {
178     auto callbacks = pCallbacks.lock();
179     if (!callbacks) {
180         HILOGI("callback function onAllBundlesEnd has already been released");
181         return;
182     }
183     if (!bool(callbacks->onAllBundlesEnd)) {
184         HILOGI("callback function onAllBundlesEnd is undefined");
185         return;
186     }
187 
188     ErrCode errCode = BError::GetBackupCodeByErrno(err);
189     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
190     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
191     HILOGI("callback function backup onAllBundlesEnd begin errCode: %{public}d", std::get<0>(errInfo));
192     auto cbCompl = [errCode {err}, errInfo](napi_env env, NError err) -> NVal {
193         if (!err && errCode == 0) {
194             return NVal::CreateUndefined(env);
195         }
196         ErrParam errorParam = [ errInfo ]() {
197             return errInfo;
198         };
199         NVal res;
200         if (err) {
201             res = NVal {env, err.GetNapiErr(env)};
202         } else {
203             res = NVal {env, NError(errorParam).GetNapiErr(env)};
204         }
205         HILOGI("callback function backup onAllBundlesEnd end errCode: %{public}d", std::get<0>(errInfo));
206         return res;
207     };
208 
209     callbacks->onAllBundlesEnd.ThreadSafeSchedule(cbCompl);
210 }
211 
OnResultReport(weak_ptr<GeneralCallbacks> pCallbacks,const std::string bundleName,const std::string result)212 static void OnResultReport(weak_ptr<GeneralCallbacks> pCallbacks, const std::string bundleName,
213     const std::string result)
214 {
215     HILOGI("Callback OnResultReport, bundleName=%{public}s", bundleName.c_str());
216     auto callbacks = pCallbacks.lock();
217     if (!callbacks) {
218         HILOGI("callback function onResultReport has already been released");
219         return;
220     }
221     if (!bool(callbacks->onResultReport)) {
222         HILOGI("callback function onResultReport is undefined");
223         return;
224     }
225     auto cbCompl = [bName {bundleName}, res {result}](napi_env env, vector<napi_value> &argv) -> bool {
226         napi_value napi_bName = nullptr;
227         if (napi_create_string_utf8(env, bName.c_str(), bName.size(), &napi_bName) != napi_ok) {
228             HILOGE("create napi string failed");
229             return false;
230         }
231         argv.emplace_back(napi_bName);
232         napi_value napi_res = nullptr;
233         if (napi_create_string_utf8(env, res.c_str(), res.size(), &napi_res) != napi_ok) {
234             HILOGE("create napi string failed");
235             return false;
236         }
237         argv.emplace_back(napi_res);
238         return true;
239     };
240     callbacks->onResultReport.CallJsMethod(cbCompl);
241 }
242 
OnBackupServiceDied(weak_ptr<GeneralCallbacks> pCallbacks)243 static void OnBackupServiceDied(weak_ptr<GeneralCallbacks> pCallbacks)
244 {
245     HILOGI("Callback OnBackupServiceDied.");
246     auto callbacks = pCallbacks.lock();
247     if (!callbacks) {
248         HILOGI("js callback function onBackupServiceDied has already been released");
249         return;
250     }
251     if (!bool(callbacks->onBackupServiceDied)) {
252         HILOGI("callback function onBackupServiceDied is undefined");
253         return;
254     }
255 
256     auto cbCompl = [](napi_env env, vector<napi_value> &argv) -> bool {
257         argv.emplace_back(nullptr);
258         napi_value napi_res = nullptr;
259         if (napi_get_undefined(env, &napi_res) != napi_ok) {
260             HILOGE("create undefined napi object failed");
261             return false;
262         }
263         argv.emplace_back(napi_res);
264         return true;
265     };
266     callbacks->onBackupServiceDied.CallJsMethod(cbCompl);
267 }
268 
OnProcess(weak_ptr<GeneralCallbacks> pCallbacks,const BundleName name,const std::string processInfo)269 static void OnProcess(weak_ptr<GeneralCallbacks> pCallbacks, const BundleName name, const std::string processInfo)
270 {
271     HILOGI("Callback OnProcess, bundleName=%{public}s", name.c_str());
272     auto callbacks = pCallbacks.lock();
273     if (!callbacks) {
274         HILOGI("callback function OnProcess has already been released");
275         return;
276     }
277     if (!bool(callbacks->onProcess)) {
278         HILOGI("callback function OnProcess is undefined");
279         return;
280     }
281     auto cbCompl = [bundleName {name}, process {processInfo}](napi_env env, vector<napi_value> &argv) -> bool {
282         napi_value napi_bName = nullptr;
283         if (napi_create_string_utf8(env, bundleName.c_str(), bundleName.size(), &napi_bName) != napi_ok) {
284             HILOGE("create napi string failed");
285             return false;
286         }
287         argv.emplace_back(napi_bName);
288         napi_value napi_process = nullptr;
289         if (napi_create_string_utf8(env, process.c_str(), process.size(), &napi_process) != napi_ok) {
290             HILOGE("create napi string failed");
291             return false;
292         }
293         argv.emplace_back(napi_process);
294         return true;
295     };
296     callbacks->onProcess.CallJsMethod(cbCompl);
297 }
298 
SetSessionBackupEntity(napi_env env,NFuncArg & funcArg,std::unique_ptr<BackupEntity> backupEntity)299 static bool SetSessionBackupEntity(napi_env env, NFuncArg &funcArg, std::unique_ptr<BackupEntity> backupEntity)
300 {
301     auto finalize = [](napi_env env, void *data, void *hint) {
302         std::unique_ptr<BackupEntity> entity = std::unique_ptr<BackupEntity>(static_cast<BackupEntity *>(data));
303         if (entity == nullptr) {
304             HILOGE("Entity is nullptr");
305             return;
306         }
307         if (entity->callbacks == nullptr) {
308             HILOGE("Callbacks is nullptr");
309             return;
310         }
311         entity->callbacks->RemoveCallbackRef();
312     };
313     if (napi_wrap(env, funcArg.GetThisVar(), backupEntity.release(), finalize, nullptr, nullptr) != napi_ok) {
314         HILOGE("Failed to set BackupEntity entity.");
315         return false;
316     }
317     return true;
318 }
319 
OnBackupSizeReport(weak_ptr<GeneralCallbacks> pCallbacks,const std::string scannedResult)320 static void OnBackupSizeReport(weak_ptr<GeneralCallbacks> pCallbacks, const std::string scannedResult)
321 {
322     HILOGI("Callback OnBackupSizeReport...");
323     auto callbacks = pCallbacks.lock();
324     if (!callbacks) {
325         HILOGE("callback function OnScanning has already been released");
326         return;
327     }
328     if (!bool(callbacks->onBackupSizeReport)) {
329         HILOGE("callback function OnScanning is undefined");
330         return;
331     }
332     auto cbCompl = [scannedInfo {scannedResult}](napi_env env, vector<napi_value> &argv) -> bool {
333         napi_value napi_scanned = nullptr;
334         if (napi_create_string_utf8(env, scannedInfo.c_str(), scannedInfo.size(), &napi_scanned) != napi_ok) {
335             HILOGE("create napi string failed");
336             return false;
337         }
338         argv.push_back(napi_scanned);
339         return true;
340     };
341     callbacks->onBackupSizeReport.CallJsMethod(cbCompl);
342 }
343 
Constructor(napi_env env,napi_callback_info cbinfo)344 napi_value SessionBackupNExporter::Constructor(napi_env env, napi_callback_info cbinfo)
345 {
346     HILOGD("called SessionBackup::Constructor begin");
347     if (!SAUtils::CheckBackupPermission()) {
348         NError(E_PERMISSION).ThrowErr(env);
349         return nullptr;
350     }
351     if (!SAUtils::IsSystemApp()) {
352         NError(E_PERMISSION_SYS).ThrowErr(env);
353         return nullptr;
354     }
355     NFuncArg funcArg(env, cbinfo);
356     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
357         HILOGE("Number of arguments unmatched.");
358         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
359         return nullptr;
360     }
361     NVal callbacks(env, funcArg[NARG_POS::FIRST]);
362     if (!callbacks.TypeIs(napi_object)) {
363         HILOGE("First argument is not an object.");
364         NError(BError(BError::Codes::SDK_INVAL_ARG, "First argument is not an object.").GetCode()).ThrowErr(env);
365         return nullptr;
366     }
367     NVal ptr(env, funcArg.GetThisVar());
368     auto backupEntity = std::make_unique<BackupEntity>();
369     backupEntity->callbacks = make_shared<GeneralCallbacks>(env, ptr, callbacks);
370     ErrCode errCode;
371     std::string errMsg;
372     backupEntity->session = BSessionBackup::Init(BSessionBackup::Callbacks {
373         .onFileReady = bind(OnFileReady, backupEntity->callbacks, placeholders::_1, placeholders::_2, placeholders::_3),
374         .onBundleStarted = bind(onBundleBegin, backupEntity->callbacks, placeholders::_1, placeholders::_2),
375         .onBundleFinished = bind(onBundleEnd, backupEntity->callbacks, placeholders::_1, placeholders::_2),
376         .onAllBundlesFinished = bind(onAllBundlesEnd, backupEntity->callbacks, placeholders::_1),
377         .onResultReport = bind(OnResultReport, backupEntity->callbacks, placeholders::_1, placeholders::_2),
378         .onBackupServiceDied = bind(OnBackupServiceDied, backupEntity->callbacks),
379         .onProcess = bind(OnProcess, backupEntity->callbacks, placeholders::_1, placeholders::_2),
380         .onBackupSizeReport = bind(OnBackupSizeReport, backupEntity->callbacks, placeholders::_1)}, errMsg, errCode);
381     if (!backupEntity->session) {
382         std::tuple<uint32_t, std::string> errInfo = (errCode == BError(BError::Codes::SA_SESSION_CONFLICT)) ?
383             std::make_tuple(errCode, errMsg) : std::make_tuple(errCode, BError::GetBackupMsgByErrno(errCode));
384         ErrParam errorParam = [ errInfo ]() { return errInfo;};
385         NError(errorParam).ThrowErr(env);
386         return nullptr;
387     }
388     if (!SetSessionBackupEntity(env, funcArg, std::move(backupEntity))) {
389         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to set BackupEntity entity").GetCode()).ThrowErr(env);
390         return nullptr;
391     }
392     HILOGD("called SessionBackup::Constructor end");
393     return funcArg.GetThisVar();
394 }
395 
GetLocalCapabilities(napi_env env,napi_callback_info cbinfo)396 napi_value SessionBackupNExporter::GetLocalCapabilities(napi_env env, napi_callback_info cbinfo)
397 {
398     HILOGI("called SessionBackup, GetLocalCapabilities Begin");
399     if (!SAUtils::CheckBackupPermission()) {
400         HILOGE("Has not permission!");
401         NError(E_PERMISSION).ThrowErr(env);
402         return nullptr;
403     }
404     if (!SAUtils::IsSystemApp()) {
405         HILOGE("System App check fail!");
406         NError(E_PERMISSION_SYS).ThrowErr(env);
407         return nullptr;
408     }
409     NFuncArg funcArg(env, cbinfo);
410     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
411         HILOGE("Number of arguments unmatched.");
412         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
413         return nullptr;
414     }
415     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
416     if (!(backupEntity && backupEntity->session)) {
417         HILOGE("Failed to get backupSession entity.");
418         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
419         return nullptr;
420     }
421     auto fd = make_shared<UniqueFd>();
422     auto cbExec = [session {backupEntity->session.get()}, fd]() -> NError {
423         if (!session) {
424             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
425         }
426         *fd = session->GetLocalCapabilities();
427         return NError(ERRNO_NOERR);
428     };
429     auto cbCompl = [fd](napi_env env, NError err) -> NVal {
430         NVal obj = NVal::CreateObject(env);
431         obj.AddProp({NVal::DeclareNapiProperty(BConstants::FD.c_str(), NVal::CreateInt32(env, fd->Release()).val_)});
432         return {obj};
433     };
434     NVal thisVar(env, funcArg.GetThisVar());
435     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
436 }
437 
GetBackupDataSize(napi_env env,napi_callback_info cbinfo)438 napi_value SessionBackupNExporter::GetBackupDataSize(napi_env env, napi_callback_info cbinfo)
439 {
440     HILOGI("called GetBackupDataSize Begin");
441     if (!SAUtils::CheckBackupPermission()) {
442         HILOGE("Has no permission!");
443         NError(E_PERMISSION).ThrowErr(env);
444         return nullptr;
445     }
446     if (!SAUtils::IsSystemApp()) {
447         HILOGE("System app check failed!");
448         NError(E_PERMISSION_SYS).ThrowErr(env);
449         return nullptr;
450     }
451     NFuncArg funcArg(env, cbinfo);
452     std::vector<BIncrementalData> bundleNames;
453     bool isPreciseScan;
454     if (!Parse::VerifyAndParseParams(env, funcArg, isPreciseScan, bundleNames)) {
455         HILOGE("VerifyAndParseParams failed");
456         return nullptr;
457     }
458     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
459     if (!(backupEntity && backupEntity->session)) {
460         HILOGE("Failed to get backupSession entity.");
461         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
462         return nullptr;
463     }
464     auto cbExec = [session {backupEntity->session.get()}, isPreciseScan {isPreciseScan},
465         bundleNames {move(bundleNames)}]() -> NError {
466         if (!session) {
467             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
468         }
469         auto ret = session->GetBackupDataSize(isPreciseScan, bundleNames);
470         if (ret != ERR_OK) {
471             return NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to GetBackupDataSize").GetCode());
472         }
473         HILOGI("GetBackupDataSize end");
474         return NError(ERRNO_NOERR);
475     };
476     auto cbCompl = [](napi_env env, NError err) -> NVal {
477         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
478     };
479     NVal thisVar(env, funcArg.GetThisVar());
480     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
481 }
482 
VerifyParamSuccess(NFuncArg & funcArg,std::vector<std::string> & bundleNames,std::vector<std::string> & bundleInfos,napi_env env)483 static bool VerifyParamSuccess(NFuncArg &funcArg, std::vector<std::string> &bundleNames,
484     std::vector<std::string> &bundleInfos, napi_env env)
485 {
486     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
487         HILOGE("Number of arguments unmatched.");
488         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
489         return false;
490     }
491     NVal jsBundles(env, funcArg[NARG_POS::FIRST]);
492     auto [succ, jsBundleNames, ignore] = jsBundles.ToStringArray();
493     if (!succ) {
494         HILOGE("First argument is not bundles array.");
495         NError(BError(BError::Codes::SDK_INVAL_ARG, "First argument is not bundles array.").GetCode()).ThrowErr(env);
496         return false;
497     }
498     bundleNames = jsBundleNames;
499     NVal jsInfos(env, funcArg[NARG_POS::SECOND]);
500     if (jsInfos.TypeIs(napi_undefined) || jsInfos.TypeIs(napi_null)) {
501         HILOGW("Third param is not exist");
502         return true;
503     }
504     auto [deSuc, jsBundleInfos, deIgnore] = jsInfos.ToStringArray();
505     if (deSuc) {
506         bundleInfos = jsBundleInfos;
507         if (bundleNames.size() != bundleInfos.size()) {
508             HILOGE("bundleNames count is not equals bundleInfos count");
509             return false;
510         }
511         return true;
512     }
513     HILOGI("Second param is callback");
514     return true;
515 }
516 
AppendBundles(napi_env env,napi_callback_info cbinfo)517 napi_value SessionBackupNExporter::AppendBundles(napi_env env, napi_callback_info cbinfo)
518 {
519     HILOGD("called SessionBackup::AppendBundles begin");
520     if (!SAUtils::CheckBackupPermission()) {
521         HILOGE("Has not permission!");
522         NError(E_PERMISSION).ThrowErr(env);
523         return nullptr;
524     }
525     if (!SAUtils::IsSystemApp()) {
526         HILOGE("System App check fail!");
527         NError(E_PERMISSION_SYS).ThrowErr(env);
528         return nullptr;
529     }
530     std::vector<std::string> bundleNames;
531     std::vector<std::string> bundleInfos;
532     NFuncArg funcArg(env, cbinfo);
533     if (!VerifyParamSuccess(funcArg, bundleNames, bundleInfos, env)) {
534         HILOGE("VerifyParamSuccess fail");
535         return nullptr;
536     }
537     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
538     if (!(backupEntity && backupEntity->session)) {
539         HILOGE("Failed to get backupSession entity.");
540         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
541         return nullptr;
542     }
543 
544     auto cbExec = [session {backupEntity->session.get()}, bundles {bundleNames}, infos {bundleInfos}]() -> NError {
545         if (!session) {
546             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
547         }
548         if (!infos.empty()) {
549             return NError(session->AppendBundles(bundles, infos));
550         }
551         return NError(session->AppendBundles(bundles));
552     };
553     auto cbCompl = [](napi_env env, NError err) -> NVal {
554         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
555     };
556 
557     HILOGD("Called SessionBackup::AppendBundles end.");
558 
559     NVal thisVar(env, funcArg.GetThisVar());
560     if (funcArg.GetArgc() == NARG_CNT::ONE) {
561         return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
562     } else if (!bundleInfos.empty()) {
563         return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
564     } else {
565         NVal cb(env, funcArg[NARG_POS::SECOND]);
566         return NAsyncWorkCallback(env, thisVar, cb).Schedule(className, cbExec, cbCompl).val_;
567     }
568 }
569 
Release(napi_env env,napi_callback_info cbinfo)570 napi_value SessionBackupNExporter::Release(napi_env env, napi_callback_info cbinfo)
571 {
572     HILOGD("called SessionBackup::Release begin");
573     if (!SAUtils::CheckBackupPermission()) {
574         HILOGE("Has not permission!");
575         NError(E_PERMISSION).ThrowErr(env);
576         return nullptr;
577     }
578     if (!SAUtils::IsSystemApp()) {
579         HILOGE("System App check fail!");
580         NError(E_PERMISSION_SYS).ThrowErr(env);
581         return nullptr;
582     }
583     NFuncArg funcArg(env, cbinfo);
584     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
585         HILOGE("Number of arguments unmatched.");
586         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
587         return nullptr;
588     }
589 
590     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
591     if (!(backupEntity && backupEntity->session)) {
592         HILOGE("Failed to get backupSession entity.");
593         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
594         return nullptr;
595     }
596 
597     auto cbExec = [session {backupEntity->session.get()}]() -> NError {
598         if (!session) {
599             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
600         }
601         return NError(session->Release());
602     };
603     auto cbCompl = [](napi_env env, NError err) -> NVal {
604         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
605     };
606 
607     HILOGD("Called SessionBackup::Release end.");
608 
609     NVal thisVar(env, funcArg.GetThisVar());
610     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
611 }
612 
Cancel(napi_env env,napi_callback_info info)613 napi_value SessionBackupNExporter::Cancel(napi_env env, napi_callback_info info)
614 {
615     HILOGI("Called SessionBackup::Cancel begin");
616     if (!SAUtils::CheckBackupPermission()) {
617         HILOGE("Has not permission!");
618         NError(E_PERMISSION).ThrowErr(env);
619         return nullptr;
620     }
621     if (!SAUtils::IsSystemApp()) {
622         HILOGE("System App check fail!");
623         NError(E_PERMISSION_SYS).ThrowErr(env);
624         return nullptr;
625     }
626     NFuncArg funcArg(env, info);
627     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
628         HILOGE("Number of arguments unmatched.");
629         NError(E_PARAMS).ThrowErr(env);
630         return nullptr;
631     }
632     NVal jsBundleStr(env, funcArg[NARG_POS::FIRST]);
633     auto [succStr, bundle, sizeStr] = jsBundleStr.ToUTF8String();
634     if (!succStr) {
635         HILOGE("First argument is not bundleName.");
636         NError(E_PARAMS).ThrowErr(env);
637         return nullptr;
638     }
639     std::string bundleName = bundle.get();
640 
641     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
642     if (!(backupEntity && backupEntity->session)) {
643         HILOGE("Failed to get backupSession entity.");
644         return nullptr;
645     }
646 
647     int result = backupEntity->session->Cancel(bundleName);
648     napi_value nResult;
649     napi_status status = napi_create_int32(env, result, &nResult);
650     if (status != napi_ok) {
651         HILOGE("napi_create_int32 faild.");
652         return nullptr;
653     }
654     HILOGI("Cancel success with result: %{public}d", result);
655     return nResult;
656 }
657 
CleanBundleTempDirCBExec(napi_env env,const NFuncArg & funcArg,std::unique_ptr<char[]> bundleName)658 static NContextCBExec CleanBundleTempDirCBExec(napi_env env,
659                                                const NFuncArg &funcArg, std::unique_ptr<char[]> bundleName)
660 {
661     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
662     if (!(backupEntity && (backupEntity->session))) {
663         HILOGE("Failed to get BackupSession entity.");
664         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get BackupSession entity.").GetCode()).ThrowErr(env);
665         return nullptr;
666     }
667     return [entity {backupEntity}, bundleName {std::string(bundleName.get())}]() -> NError {
668         if (!(entity && (entity->session))) {
669             return NError(BError(BError::Codes::SDK_INVAL_ARG, "Backup session is nullptr").GetCode());
670         }
671         return NError(entity->session->CleanBundleTempDir(bundleName));
672     };
673 }
674 
CleanBundleTempDir(napi_env env,napi_callback_info cbinfo)675 napi_value SessionBackupNExporter::CleanBundleTempDir(napi_env env, napi_callback_info cbinfo)
676 {
677     HILOGI("Called SessionBackupNExporter::CleanBundleTempDir begin.");
678     if (!SAUtils::CheckBackupPermission()) {
679         HILOGE("Has not permission!");
680         NError(E_PERMISSION).ThrowErr(env);
681         return nullptr;
682     }
683     if (!SAUtils::IsSystemApp()) {
684         HILOGE("System App check fail!");
685         NError(E_PERMISSION_SYS).ThrowErr(env);
686         return nullptr;
687     }
688     NFuncArg funcArg(env, cbinfo);
689     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
690         HILOGE("Number of arguments unmatched");
691         NError(E_PARAMS).ThrowErr(env);
692         return nullptr;
693     }
694     NVal jsBundleStr(env, funcArg[NARG_POS::FIRST]);
695     auto [succ, bundleName, sizeStr] = jsBundleStr.ToUTF8String();
696     if (!succ) {
697         HILOGE("First arguments is not string.");
698         NError(E_PARAMS).ThrowErr(env);
699         return nullptr;
700     }
701 
702     auto cbExec = CleanBundleTempDirCBExec(env, funcArg, std::move(bundleName));
703     if (cbExec == nullptr) {
704         HILOGE("CleanBundleTempDirCBExec fail!");
705         return nullptr;
706     }
707     auto cbCompl = [](napi_env env, NError err) -> NVal {
708         return err ? NVal::CreateBool(env, false) : NVal::CreateBool(env, true);
709     };
710 
711     NVal thisVar(env, funcArg.GetThisVar());
712     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
713 }
714 
GetCompatibilityInfoCBExec(napi_env env,const NFuncArg & funcArg,string bundleName,string extInfo,shared_ptr<string> compatInfo)715 static NContextCBExec GetCompatibilityInfoCBExec(napi_env env, const NFuncArg &funcArg, string bundleName,
716     string extInfo, shared_ptr<string> compatInfo)
717 {
718     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
719     if (!(backupEntity && (backupEntity->session))) {
720         HILOGE("Failed to get BackupSession entity.");
721         return nullptr;
722     }
723     return [entity {backupEntity}, bundleName, extInfo, compatInfo]() -> NError {
724         if (!(entity && (entity->session))) {
725             return NError(BError(BError::Codes::SDK_INVAL_ARG, "Backup session is nullptr").GetCode());
726         }
727         return NError(entity->session->GetCompatibilityInfo(bundleName, extInfo, *compatInfo));
728     };
729 }
730 
ParseCompatInfoParam(napi_env env,NFuncArg & funcArg,string & bundleName,string & extInfo)731 static bool ParseCompatInfoParam(napi_env env, NFuncArg &funcArg, string &bundleName, string &extInfo)
732 {
733     if (!funcArg.InitArgs(NARG_CNT::TWO)) {
734         HILOGE("Number of arguments unmatched");
735         return false;
736     }
737     NVal jsBundleName(env, funcArg[NARG_POS::FIRST]);
738     auto [succ, bundleNamePtr, sizeStr] = jsBundleName.ToUTF8String();
739     if (!succ) {
740         HILOGE("First arguments is not string.");
741         return false;
742     }
743     NVal jsExtInfo(env, funcArg[NARG_POS::SECOND]);
744     auto [succ1, extInfoPtr, sizeStr1] = jsExtInfo.ToUTF8String();
745     if (!succ1) {
746         HILOGE("Second arguments is not string.");
747         return false;
748     }
749     bundleName = string(bundleNamePtr.get());
750     extInfo = string(extInfoPtr.get());
751     return true;
752 }
753 
GetCompatibilityInfo(napi_env env,napi_callback_info cbinfo)754 napi_value SessionBackupNExporter::GetCompatibilityInfo(napi_env env, napi_callback_info cbinfo)
755 {
756     HILOGI("Called SessionBackupNExporter::GetCompatibilityInfo begin.");
757     if (!SAUtils::CheckBackupPermission()) {
758         HILOGE("Has not permission!");
759         NError(E_PERMISSION).ThrowErr(env);
760         return nullptr;
761     }
762     if (!SAUtils::IsSystemApp()) {
763         HILOGE("System App check fail!");
764         NError(E_PERMISSION_SYS).ThrowErr(env);
765         return nullptr;
766     }
767 
768     NFuncArg funcArg(env, cbinfo);
769     string bundleName;
770     string extInfo;
771     if (!ParseCompatInfoParam(env, funcArg, bundleName, extInfo)) {
772         NError(E_PARAMS).ThrowErr(env);
773         return nullptr;
774     }
775 
776     auto compatInfo = std::make_shared<string>();
777     auto cbExec = GetCompatibilityInfoCBExec(env, funcArg, bundleName, extInfo, compatInfo);
778     if (cbExec == nullptr) {
779         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get BackupSession entity.").GetCode()).ThrowErr(env);
780         return nullptr;
781     }
782     auto cbCompl = [compatInfo](napi_env env, NError err) -> NVal {
783         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUTF8String(env, *compatInfo);
784     };
785 
786     NVal thisVar(env, funcArg.GetThisVar());
787     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
788 }
789 
Export()790 bool SessionBackupNExporter::Export()
791 {
792     HILOGD("called SessionBackupNExporter::Export begin");
793     vector<napi_property_descriptor> props = {
794         NVal::DeclareNapiFunction("getLocalCapabilities", GetLocalCapabilities),
795         NVal::DeclareNapiFunction("getBackupDataSize", GetBackupDataSize),
796         NVal::DeclareNapiFunction("appendBundles", AppendBundles),
797         NVal::DeclareNapiFunction("release", Release),
798         NVal::DeclareNapiFunction("cancel", Cancel),
799         NVal::DeclareNapiFunction("cleanBundleTempDir", CleanBundleTempDir),
800         NVal::DeclareNapiFunction("getCompatibilityInfo", GetCompatibilityInfo),
801     };
802 
803     auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props));
804     if (!succ) {
805         HILOGE("Failed to define class");
806         NError(EIO).ThrowErr(exports_.env_);
807         return false;
808     }
809     succ = NClass::SaveClass(exports_.env_, className, classValue);
810     if (!succ) {
811         HILOGE("Failed to save class");
812         NError(EIO).ThrowErr(exports_.env_);
813         return false;
814     }
815 
816     HILOGD("called SessionBackupNExporter::Export end");
817     return exports_.AddProp(className, classValue);
818 }
819 
GetClassName()820 string SessionBackupNExporter::GetClassName()
821 {
822     return SessionBackupNExporter::className;
823 }
824 
SessionBackupNExporter(napi_env env,napi_value exports)825 SessionBackupNExporter::SessionBackupNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
826 
~SessionBackupNExporter()827 SessionBackupNExporter::~SessionBackupNExporter() {}
828 } // namespace OHOS::FileManagement::Backup