• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 #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 =
383             std::make_tuple(errCode, BError::GetBackupMsgByErrno(errCode) + ", " + errMsg);
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     UniqueFd fd;
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 fd < 0 ? NError(BError(BError::Codes::SA_INVAL_ARG, "Failed to get local capabilities.").GetCode()) :
428             NError(BError(BError::Codes::OK, "Success to get local capabilities.").GetCode());
429     };
430     auto cbCompl = [&fd](napi_env env, NError err) -> NVal {
431         NVal obj = NVal::CreateObject(env);
432         obj.AddProp({NVal::DeclareNapiProperty(BConstants::FD.c_str(), NVal::CreateInt32(env, fd.Release()).val_)});
433         return err ? NVal {env, err.GetNapiErr(env)} : obj;
434     };
435     NVal thisVar(env, funcArg.GetThisVar());
436     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
437 }
438 
GetBackupDataSize(napi_env env,napi_callback_info cbinfo)439 napi_value SessionBackupNExporter::GetBackupDataSize(napi_env env, napi_callback_info cbinfo)
440 {
441     HILOGI("called GetBackupDataSize Begin");
442     if (!SAUtils::CheckBackupPermission()) {
443         HILOGE("Has no permission!");
444         NError(E_PERMISSION).ThrowErr(env);
445         return nullptr;
446     }
447     if (!SAUtils::IsSystemApp()) {
448         HILOGE("System app check failed!");
449         NError(E_PERMISSION_SYS).ThrowErr(env);
450         return nullptr;
451     }
452     NFuncArg funcArg(env, cbinfo);
453     std::vector<BIncrementalData> bundleNames;
454     bool isPreciseScan;
455     if (!Parse::VerifyAndParseParams(env, funcArg, isPreciseScan, bundleNames)) {
456         HILOGE("VerifyAndParseParams failed");
457         return nullptr;
458     }
459     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
460     if (!(backupEntity && backupEntity->session)) {
461         HILOGE("Failed to get backupSession entity.");
462         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
463         return nullptr;
464     }
465     auto cbExec = [session {backupEntity->session.get()}, isPreciseScan {isPreciseScan},
466         bundleNames {move(bundleNames)}]() -> NError {
467         if (!session) {
468             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
469         }
470         auto ret = session->GetBackupDataSize(isPreciseScan, bundleNames);
471         if (ret != ERR_OK) {
472             return NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to GetBackupDataSize").GetCode());
473         }
474         HILOGI("GetBackupDataSize end");
475         return NError(ERRNO_NOERR);
476     };
477     auto cbCompl = [](napi_env env, NError err) -> NVal {
478         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
479     };
480     NVal thisVar(env, funcArg.GetThisVar());
481     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
482 }
483 
VerifyParamSuccess(NFuncArg & funcArg,std::vector<std::string> & bundleNames,std::vector<std::string> & bundleInfos,napi_env env)484 static bool VerifyParamSuccess(NFuncArg &funcArg, std::vector<std::string> &bundleNames,
485     std::vector<std::string> &bundleInfos, napi_env env)
486 {
487     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
488         HILOGE("Number of arguments unmatched.");
489         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
490         return false;
491     }
492     NVal jsBundles(env, funcArg[NARG_POS::FIRST]);
493     auto [succ, jsBundleNames, ignore] = jsBundles.ToStringArray();
494     if (!succ) {
495         HILOGE("First argument is not bundles array.");
496         NError(BError(BError::Codes::SDK_INVAL_ARG, "First argument is not bundles array.").GetCode()).ThrowErr(env);
497         return false;
498     }
499     bundleNames = jsBundleNames;
500     NVal jsInfos(env, funcArg[NARG_POS::SECOND]);
501     if (jsInfos.TypeIs(napi_undefined) || jsInfos.TypeIs(napi_null)) {
502         HILOGW("Third param is not exist");
503         return true;
504     }
505     auto [deSuc, jsBundleInfos, deIgnore] = jsInfos.ToStringArray();
506     if (deSuc) {
507         bundleInfos = jsBundleInfos;
508         if (bundleNames.size() != bundleInfos.size()) {
509             HILOGE("bundleNames count is not equals bundleInfos count");
510             return false;
511         }
512         return true;
513     }
514     HILOGI("Second param is callback");
515     return true;
516 }
517 
AppendBundles(napi_env env,napi_callback_info cbinfo)518 napi_value SessionBackupNExporter::AppendBundles(napi_env env, napi_callback_info cbinfo)
519 {
520     HILOGD("called SessionBackup::AppendBundles begin");
521     if (!SAUtils::CheckBackupPermission()) {
522         HILOGE("Has not permission!");
523         NError(E_PERMISSION).ThrowErr(env);
524         return nullptr;
525     }
526     if (!SAUtils::IsSystemApp()) {
527         HILOGE("System App check fail!");
528         NError(E_PERMISSION_SYS).ThrowErr(env);
529         return nullptr;
530     }
531     std::vector<std::string> bundleNames;
532     std::vector<std::string> bundleInfos;
533     NFuncArg funcArg(env, cbinfo);
534     if (!VerifyParamSuccess(funcArg, bundleNames, bundleInfos, env)) {
535         HILOGE("VerifyParamSuccess fail");
536         return nullptr;
537     }
538     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
539     if (!(backupEntity && backupEntity->session)) {
540         HILOGE("Failed to get backupSession entity.");
541         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
542         return nullptr;
543     }
544 
545     auto cbExec = [session {backupEntity->session.get()}, bundles {bundleNames}, infos {bundleInfos}]() -> NError {
546         if (!session) {
547             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
548         }
549         if (!infos.empty()) {
550             return NError(session->AppendBundles(bundles, infos));
551         }
552         return NError(session->AppendBundles(bundles));
553     };
554     auto cbCompl = [](napi_env env, NError err) -> NVal {
555         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
556     };
557 
558     HILOGD("Called SessionBackup::AppendBundles end.");
559 
560     NVal thisVar(env, funcArg.GetThisVar());
561     if (funcArg.GetArgc() == NARG_CNT::ONE) {
562         return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
563     } else if (!bundleInfos.empty()) {
564         return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
565     } else {
566         NVal cb(env, funcArg[NARG_POS::SECOND]);
567         return NAsyncWorkCallback(env, thisVar, cb).Schedule(className, cbExec, cbCompl).val_;
568     }
569 }
570 
Release(napi_env env,napi_callback_info cbinfo)571 napi_value SessionBackupNExporter::Release(napi_env env, napi_callback_info cbinfo)
572 {
573     HILOGD("called SessionBackup::Release begin");
574     if (!SAUtils::CheckBackupPermission()) {
575         HILOGE("Has not permission!");
576         NError(E_PERMISSION).ThrowErr(env);
577         return nullptr;
578     }
579     if (!SAUtils::IsSystemApp()) {
580         HILOGE("System App check fail!");
581         NError(E_PERMISSION_SYS).ThrowErr(env);
582         return nullptr;
583     }
584     NFuncArg funcArg(env, cbinfo);
585     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
586         HILOGE("Number of arguments unmatched.");
587         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
588         return nullptr;
589     }
590 
591     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
592     if (!(backupEntity && backupEntity->session)) {
593         HILOGE("Failed to get backupSession entity.");
594         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
595         return nullptr;
596     }
597 
598     auto cbExec = [session {backupEntity->session.get()}]() -> NError {
599         if (!session) {
600             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
601         }
602         return NError(session->Release());
603     };
604     auto cbCompl = [](napi_env env, NError err) -> NVal {
605         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
606     };
607 
608     HILOGD("Called SessionBackup::Release end.");
609 
610     NVal thisVar(env, funcArg.GetThisVar());
611     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
612 }
613 
Cancel(napi_env env,napi_callback_info info)614 napi_value SessionBackupNExporter::Cancel(napi_env env, napi_callback_info info)
615 {
616     HILOGI("Called SessionBackup::Cancel begin");
617     if (!SAUtils::CheckBackupPermission()) {
618         HILOGE("Has not permission!");
619         NError(E_PERMISSION).ThrowErr(env);
620         return nullptr;
621     }
622     if (!SAUtils::IsSystemApp()) {
623         HILOGE("System App check fail!");
624         NError(E_PERMISSION_SYS).ThrowErr(env);
625         return nullptr;
626     }
627     NFuncArg funcArg(env, info);
628     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
629         HILOGE("Number of arguments unmatched.");
630         NError(E_PARAMS).ThrowErr(env);
631         return nullptr;
632     }
633     NVal jsBundleStr(env, funcArg[NARG_POS::FIRST]);
634     auto [succStr, bundle, sizeStr] = jsBundleStr.ToUTF8String();
635     if (!succStr) {
636         HILOGE("First argument is not bundleName.");
637         NError(E_PARAMS).ThrowErr(env);
638         return nullptr;
639     }
640     std::string bundleName = bundle.get();
641 
642     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
643     if (!(backupEntity && backupEntity->session)) {
644         HILOGE("Failed to get backupSession entity.");
645         return nullptr;
646     }
647 
648     int result = backupEntity->session->Cancel(bundleName);
649     napi_value nResult;
650     napi_status status = napi_create_int32(env, result, &nResult);
651     if (status != napi_ok) {
652         HILOGE("napi_create_int32 faild.");
653         return nullptr;
654     }
655     HILOGI("Cancel success with result: %{public}d", result);
656     return nResult;
657 }
658 
Export()659 bool SessionBackupNExporter::Export()
660 {
661     HILOGD("called SessionBackupNExporter::Export begin");
662     vector<napi_property_descriptor> props = {
663         NVal::DeclareNapiFunction("getLocalCapabilities", GetLocalCapabilities),
664         NVal::DeclareNapiFunction("getBackupDataSize", GetBackupDataSize),
665         NVal::DeclareNapiFunction("appendBundles", AppendBundles),
666         NVal::DeclareNapiFunction("release", Release),
667         NVal::DeclareNapiFunction("cancel", Cancel),
668     };
669 
670     auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props));
671     if (!succ) {
672         HILOGE("Failed to define class");
673         NError(EIO).ThrowErr(exports_.env_);
674         return false;
675     }
676     succ = NClass::SaveClass(exports_.env_, className, classValue);
677     if (!succ) {
678         HILOGE("Failed to save class");
679         NError(EIO).ThrowErr(exports_.env_);
680         return false;
681     }
682 
683     HILOGD("called SessionBackupNExporter::Export end");
684     return exports_.AddProp(className, classValue);
685 }
686 
GetClassName()687 string SessionBackupNExporter::GetClassName()
688 {
689     return SessionBackupNExporter::className;
690 }
691 
SessionBackupNExporter(napi_env env,napi_value exports)692 SessionBackupNExporter::SessionBackupNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
693 
~SessionBackupNExporter()694 SessionBackupNExporter::~SessionBackupNExporter() {}
695 } // namespace OHOS::FileManagement::Backup