1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "session_incremental_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_incremental_backup_session.h"
23 #include "b_incremental_data.h"
24 #include "b_resources/b_constants.h"
25 #include "b_sa/b_sa_utils.h"
26 #include "backup_kit_inner.h"
27 #include "directory_ex.h"
28 #include "filemgmt_libhilog.h"
29 #include "general_callbacks.h"
30 #include "incremental_backup_data.h"
31 #include "service_proxy.h"
32 
33 namespace OHOS::FileManagement::Backup {
34 using namespace std;
35 using namespace LibN;
36 
37 struct BackupEntity {
38     unique_ptr<BIncrementalBackupSession> session;
39     shared_ptr<GeneralCallbacks> callbacks;
40 };
41 
OnFileReady(weak_ptr<GeneralCallbacks> pCallbacks,const BFileInfo & fileInfo,UniqueFd fd,UniqueFd manifestFd,int sysErrno)42 static void OnFileReady(weak_ptr<GeneralCallbacks> pCallbacks, const BFileInfo &fileInfo, UniqueFd fd,
43     UniqueFd manifestFd, int sysErrno)
44 {
45     if (pCallbacks.expired()) {
46         HILOGI("callbacks is unbound");
47         return;
48     }
49     auto callbacks = pCallbacks.lock();
50     if (!callbacks) {
51         HILOGI("callback function onFileReady has already been released");
52         return;
53     }
54     if (!bool(callbacks->onFileReady)) {
55         HILOGI("callback function onFileReady is undefined");
56         return;
57     }
58     ErrCode errCode = BError::GetCodeByErrno(sysErrno);
59     std::string errMsg = "system errno: " + to_string(sysErrno);
60     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
61 
62     auto cbCompl = [bundleName {fileInfo.owner}, fileName {fileInfo.fileName},
63                     fd {make_shared<UniqueFd>(fd.Release())},
64                     manifestFd {make_shared<UniqueFd>(manifestFd.Release())},
65                     errInfo](napi_env env, NError err) -> NVal {
66         if (err) {
67             return {env, err.GetNapiErr(env)};
68         }
69         HILOGI("callback function incremental backup onFileReady cbCompl errcode: %{public}d", std::get<0>(errInfo));
70         NVal obj;
71         ErrParam errorParam = [ errInfo ]() {
72             return errInfo;
73         };
74         if (std::get<0>(errInfo) != 0) {
75             obj = NVal {env, NError(errorParam).GetNapiErr(env)};
76             napi_status status = napi_set_named_property(env, obj.val_, FILEIO_TAG_ERR_DATA.c_str(),
77                 NVal::CreateUTF8String(env, bundleName).val_);
78             if (status != napi_ok) {
79                 HILOGE("Failed to set data, status %{public}d, bundleName %{public}s", status, bundleName.c_str());
80             }
81         } else {
82             obj = NVal::CreateObject(env);
83             obj.AddProp({
84                 NVal::DeclareNapiProperty(BConstants::BUNDLE_NAME.c_str(),
85                     NVal::CreateUTF8String(env, bundleName).val_),
86                 NVal::DeclareNapiProperty(BConstants::URI.c_str(), NVal::CreateUTF8String(env, fileName).val_),
87                 NVal::DeclareNapiProperty(BConstants::FD.c_str(), NVal::CreateInt32(env, fd->Release()).val_),
88                 NVal::DeclareNapiProperty(BConstants::MANIFEST_FD.c_str(),
89                     NVal::CreateInt32(env, manifestFd->Release()).val_)});
90         }
91         return {obj};
92     };
93 
94     callbacks->onFileReady.ThreadSafeSchedule(cbCompl);
95 }
96 
onBundleBegin(weak_ptr<GeneralCallbacks> pCallbacks,ErrCode err,const BundleName name)97 static void onBundleBegin(weak_ptr<GeneralCallbacks> pCallbacks, ErrCode err, const BundleName name)
98 {
99     HILOGI("Callback onBundleBegin, bundleName=%{public}s, errCode=%{public}d", name.c_str(), err);
100     if (pCallbacks.expired()) {
101         HILOGI("callbacks is unbound");
102         return;
103     }
104     auto callbacks = pCallbacks.lock();
105     if (!callbacks) {
106         HILOGI("callback function onBundleBegin has already been released");
107         return;
108     }
109     if (!bool(callbacks->onBundleBegin)) {
110         HILOGI("callback function onBundleBegin is undefined");
111         return;
112     }
113 
114     ErrCode errCode = BError::GetBackupCodeByErrno(err);
115     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
116     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
117 
118     auto cbCompl = [name {name}, errCode {err}, errInfo](napi_env env, NError err) -> NVal {
119         NVal bundleName = NVal::CreateUTF8String(env, name);
120         if (!err && errCode == 0) {
121             return bundleName;
122         }
123         ErrParam errorParam = [ errInfo ]() {
124             return errInfo;
125         };
126         NVal res;
127         if (err) {
128             res = NVal {env, err.GetNapiErr(env)};
129         } else {
130             res = NVal {env, NError(errorParam).GetNapiErr(env)};
131         }
132         napi_status status = napi_set_named_property(env, res.val_, FILEIO_TAG_ERR_DATA.c_str(), bundleName.val_);
133         if (status != napi_ok) {
134             HILOGE("Failed to set data property, status %{public}d, bundleName %{public}s", status, name.c_str());
135         }
136 
137         return res;
138     };
139 
140     callbacks->onBundleBegin.ThreadSafeSchedule(cbCompl);
141 }
142 
onBundleEnd(weak_ptr<GeneralCallbacks> pCallbacks,ErrCode err,const BundleName name)143 static void onBundleEnd(weak_ptr<GeneralCallbacks> pCallbacks, ErrCode err, const BundleName name)
144 {
145     HILOGI("Callback onBundleEnd, bundleName=%{public}s, errCode=%{public}d", name.c_str(), err);
146     if (pCallbacks.expired()) {
147         HILOGI("callbacks is unbound");
148         return;
149     }
150     auto callbacks = pCallbacks.lock();
151     if (!callbacks) {
152         HILOGI("callback function onBundleEnd has already been released");
153         return;
154     }
155     if (!bool(callbacks->onBundleEnd)) {
156         HILOGI("callback function onBundleEnd is undefined");
157         return;
158     }
159 
160     ErrCode errCode = BError::GetBackupCodeByErrno(err);
161     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
162     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
163 
164     auto cbCompl = [name {name}, errCode {err}, errInfo](napi_env env, NError err) -> NVal {
165         NVal bundleName = NVal::CreateUTF8String(env, name);
166         if (!err && errCode == 0) {
167             return bundleName;
168         }
169         ErrParam errorParam = [ errInfo ]() {
170             return errInfo;
171         };
172         NVal res;
173         if (err) {
174             res = NVal {env, err.GetNapiErr(env)};
175         } else {
176             res = NVal {env, NError(errorParam).GetNapiErr(env)};
177         }
178         napi_status status = napi_set_named_property(env, res.val_, FILEIO_TAG_ERR_DATA.c_str(), bundleName.val_);
179         if (status != napi_ok) {
180             HILOGE("Failed to set data property, status %{public}d, bundleName %{public}s", status, name.c_str());
181         }
182 
183         return res;
184     };
185 
186     callbacks->onBundleEnd.ThreadSafeSchedule(cbCompl);
187 }
188 
onAllBundlesEnd(weak_ptr<GeneralCallbacks> pCallbacks,ErrCode err)189 static void onAllBundlesEnd(weak_ptr<GeneralCallbacks> pCallbacks, ErrCode err)
190 {
191     if (pCallbacks.expired()) {
192         HILOGI("callbacks is unbound");
193         return;
194     }
195     auto callbacks = pCallbacks.lock();
196     if (!callbacks) {
197         HILOGI("callback function onAllBundlesEnd has already been released");
198         return;
199     }
200     if (!bool(callbacks->onAllBundlesEnd)) {
201         HILOGI("callback function onAllBundlesEnd is undefined");
202         return;
203     }
204 
205     ErrCode errCode = BError::GetBackupCodeByErrno(err);
206     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
207     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
208 
209     auto cbCompl = [errCode {err}, errInfo](napi_env env, NError err) -> NVal {
210         if (!err && errCode == 0) {
211             return NVal::CreateUndefined(env);
212         }
213         ErrParam errorParam = [ errInfo ]() {
214             return errInfo;
215         };
216         NVal res;
217         if (err) {
218             res = NVal {env, err.GetNapiErr(env)};
219         } else {
220             res = NVal {env, NError(errorParam).GetNapiErr(env)};
221         }
222 
223         return res;
224     };
225 
226     callbacks->onAllBundlesEnd.ThreadSafeSchedule(cbCompl);
227 }
228 
OnResultReport(weak_ptr<GeneralCallbacks> pCallbacks,const std::string bundleName,const std::string result)229 static void OnResultReport(weak_ptr<GeneralCallbacks> pCallbacks, const std::string bundleName,
230     const std::string result)
231 {
232     HILOGI("Callback OnResultReport, bundleName=%{public}s", bundleName.c_str());
233     if (pCallbacks.expired()) {
234         HILOGI("callbacks is unbound");
235         return;
236     }
237     auto callbacks = pCallbacks.lock();
238     if (!callbacks) {
239         HILOGI("callback function onResultReport has already been released");
240         return;
241     }
242     if (!bool(callbacks->onResultReport)) {
243         HILOGI("callback function onResultReport is undefined");
244         return;
245     }
246     auto cbCompl = [bName {bundleName}, res {result}](napi_env env, vector<napi_value> &argv) -> bool {
247         napi_value napi_bName = nullptr;
248         napi_create_string_utf8(env, bName.c_str(), bName.size(), &napi_bName);
249         argv.push_back(napi_bName);
250         napi_value napi_res = nullptr;
251         napi_create_string_utf8(env, res.c_str(), res.size(), &napi_res);
252         argv.push_back(napi_res);
253         return true;
254     };
255     callbacks->onResultReport.CallJsMethod(cbCompl);
256 }
257 
OnBackupServiceDied(weak_ptr<GeneralCallbacks> pCallbacks)258 static void OnBackupServiceDied(weak_ptr<GeneralCallbacks> pCallbacks)
259 {
260     HILOGI("Callback OnBackupServiceDied.");
261     if (pCallbacks.expired()) {
262         HILOGI("callbacks is unbound");
263         return;
264     }
265     auto callbacks = pCallbacks.lock();
266     if (!callbacks) {
267         HILOGI("js callback function onBackupServiceDied has already been released");
268         return;
269     }
270     if (!bool(callbacks->onBackupServiceDied)) {
271         HILOGI("callback function onBackupServiceDied is undefined");
272         return;
273     }
274 
275     auto cbCompl = [](napi_env env, vector<napi_value> &argv) -> bool {
276         napi_value napi_res = nullptr;
277         napi_get_undefined(env, &napi_res);
278         argv.push_back(napi_res);
279         return true;
280     };
281     callbacks->onBackupServiceDied.CallJsMethod(cbCompl);
282 }
283 
OnProcess(weak_ptr<GeneralCallbacks> pCallbacks,const BundleName name,const std::string processInfo)284 static void OnProcess(weak_ptr<GeneralCallbacks> pCallbacks, const BundleName name, const std::string processInfo)
285 {
286     HILOGI("Callback OnProcess, bundleName=%{public}s", name.c_str());
287     if (pCallbacks.expired()) {
288         HILOGI("callbacks is unbound");
289         return;
290     }
291     auto callbacks = pCallbacks.lock();
292     if (!callbacks) {
293         HILOGI("callback function OnProcess has already been released");
294         return;
295     }
296     if (!bool(callbacks->onProcess)) {
297         HILOGI("callback function OnProcess is undefined");
298         return;
299     }
300     auto cbCompl = [bundleName {name}, process {processInfo}](napi_env env, vector<napi_value> &argv) -> bool {
301         napi_value napi_bName = nullptr;
302         napi_create_string_utf8(env, bundleName.c_str(), bundleName.size(), &napi_bName);
303         argv.push_back(napi_bName);
304         napi_value napi_process = nullptr;
305         napi_create_string_utf8(env, process.c_str(), process.size(), &napi_process);
306         argv.push_back(napi_process);
307         return true;
308     };
309     callbacks->onProcess.CallJsMethod(cbCompl);
310 }
311 
Constructor(napi_env env,napi_callback_info cbinfo)312 napi_value SessionIncrementalBackupNExporter::Constructor(napi_env env, napi_callback_info cbinfo)
313 {
314     HILOGD("called SessionIncrementalBackup::Constructor begin");
315     if (!SAUtils::CheckBackupPermission()) {
316         HILOGE("Has not permission!");
317         NError(E_PERMISSION).ThrowErr(env);
318         return nullptr;
319     }
320     if (!SAUtils::IsSystemApp()) {
321         HILOGE("System App check fail!");
322         NError(E_PERMISSION_SYS).ThrowErr(env);
323         return nullptr;
324     }
325     NFuncArg funcArg(env, cbinfo);
326     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
327         HILOGE("Number of arguments unmatched");
328         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
329         return nullptr;
330     }
331 
332     NVal callbacks(env, funcArg[NARG_POS::FIRST]);
333     if (!callbacks.TypeIs(napi_object)) {
334         HILOGE("First argument is not an object.");
335         NError(BError(BError::Codes::SDK_INVAL_ARG, "First argument is not an object.").GetCode()).ThrowErr(env);
336         return nullptr;
337     }
338 
339     NVal ptr(env, funcArg.GetThisVar());
340     auto backupEntity = std::make_unique<BackupEntity>();
341     backupEntity->callbacks = make_shared<GeneralCallbacks>(env, ptr, callbacks);
342     backupEntity->session = BIncrementalBackupSession::Init(BIncrementalBackupSession::Callbacks {
343         .onFileReady = bind(OnFileReady, backupEntity->callbacks, placeholders::_1, placeholders::_2, placeholders::_3,
344             placeholders::_4),
345         .onBundleStarted = bind(onBundleBegin, backupEntity->callbacks, placeholders::_1, placeholders::_2),
346         .onBundleFinished = bind(onBundleEnd, backupEntity->callbacks, placeholders::_1, placeholders::_2),
347         .onAllBundlesFinished = bind(onAllBundlesEnd, backupEntity->callbacks, placeholders::_1),
348         .onResultReport = bind(OnResultReport, backupEntity->callbacks, placeholders::_1, placeholders::_2),
349         .onBackupServiceDied = bind(OnBackupServiceDied, backupEntity->callbacks),
350         .onProcess = bind(OnProcess, backupEntity->callbacks, placeholders::_1, placeholders::_2)});
351     if (!backupEntity->session) {
352         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to init backup").GetCode()).ThrowErr(env);
353         return nullptr;
354     }
355     if (!NClass::SetEntityFor<BackupEntity>(env, funcArg.GetThisVar(), move(backupEntity))) {
356         HILOGE("Failed to set BackupEntity entity.");
357         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to set BackupEntity entity.").GetCode()).ThrowErr(env);
358         return nullptr;
359     }
360 
361     HILOGD("called SessionIncrementalBackup::Constructor end");
362     return funcArg.GetThisVar();
363 }
364 
CheckDataList(const LibN::NVal & data)365 static bool CheckDataList(const LibN::NVal &data)
366 {
367     LibN::NVal name = data.GetProp(BConstants::BUNDLE_NAME);
368     if (name.val_ == nullptr) {
369         return false;
370     }
371     auto [succ, str, ignore] = name.ToUTF8String();
372     if (!succ) {
373         return false;
374     }
375 
376     LibN::NVal time = data.GetProp(BConstants::LAST_INCREMENTAL_TIME);
377     if (time.val_ == nullptr) {
378         return false;
379     }
380     tie(succ, ignore) = time.ToInt64();
381     if (!succ) {
382         return false;
383     }
384     return true;
385 }
386 
ParseDataList(napi_env env,const napi_value & value)387 static std::tuple<bool, std::vector<BIncrementalData>> ParseDataList(napi_env env, const napi_value& value)
388 {
389     uint32_t size = 0;
390     napi_status status = napi_get_array_length(env, value, &size);
391     if (status != napi_ok) {
392         HILOGE("Get array length failed!");
393         return {false, {}};
394     }
395     if (size == 0) {
396         HILOGI("array length is zero!");
397         return {true, {}};
398     }
399 
400     napi_value result;
401     std::vector<BIncrementalData> backupData;
402     for (uint32_t i = 0; i < size; i++) {
403         status = napi_get_element(env, value, i, &result);
404         if (status != napi_ok) {
405             HILOGE("Get element failed! index is :%{public}u", i);
406             return {false, {}};
407         } else {
408             NVal element(env, result);
409             if (!CheckDataList(element)) {
410                 HILOGE("bundles are invalid!");
411                 return {false, {}};
412             }
413             IncrementalBackupData data(element);
414             backupData.emplace_back(data.bundleName,
415                                     data.lastIncrementalTime,
416                                     data.manifestFd,
417                                     data.parameters,
418                                     data.priority);
419         }
420     }
421     return {true, backupData};
422 }
423 
VerifyParamSuccess(NFuncArg & funcArg,std::vector<BIncrementalData> & backupBundles,std::vector<std::string> & bundleInfos,napi_env env)424 static bool VerifyParamSuccess(NFuncArg &funcArg, std::vector<BIncrementalData> &backupBundles,
425     std::vector<std::string> &bundleInfos, napi_env env)
426 {
427     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
428         HILOGE("Number of arguments unmatched.");
429         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
430         return false;
431     }
432     auto [succ, bundles] = ParseDataList(env, funcArg[NARG_POS::FIRST]);
433     if (!succ) {
434         HILOGE("bundles array invalid.");
435         NError(BError(BError::Codes::SDK_INVAL_ARG, "bundles array invalid.").GetCode()).ThrowErr(env);
436         return false;
437     }
438     backupBundles = bundles;
439     NVal jsInfos(env, funcArg[NARG_POS::SECOND]);
440     if (jsInfos.TypeIs(napi_undefined) || jsInfos.TypeIs(napi_null)) {
441         HILOGW("Third param is not exist");
442         return true;
443     }
444     auto [deSuc, jsBundleInfos, deIgnore] = jsInfos.ToStringArray();
445     if (deSuc) {
446         bundleInfos = jsBundleInfos;
447         if (backupBundles.size() != bundleInfos.size()) {
448             HILOGE("backupBundles count is not equals bundleInfos count");
449             return false;
450         }
451         return true;
452     }
453     HILOGI("Second param is callback");
454     return true;
455 }
456 
AppendBundles(napi_env env,napi_callback_info cbinfo)457 napi_value SessionIncrementalBackupNExporter::AppendBundles(napi_env env, napi_callback_info cbinfo)
458 {
459     HILOGD("called SessionIncrementalBackup::AppendBundles begin");
460     if (!SAUtils::CheckBackupPermission()) {
461         HILOGE("Has not permission!");
462         NError(E_PERMISSION).ThrowErr(env);
463         return nullptr;
464     }
465     if (!SAUtils::IsSystemApp()) {
466         HILOGE("System App check fail!");
467         NError(E_PERMISSION_SYS).ThrowErr(env);
468         return nullptr;
469     }
470     std::vector<BIncrementalData> backupBundles;
471     std::vector<std::string> bundleInfos;
472     NFuncArg funcArg(env, cbinfo);
473     if (!VerifyParamSuccess(funcArg, backupBundles, bundleInfos, env)) {
474         HILOGE("VerifyParamSuccess fail");
475         return nullptr;
476     }
477     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
478     if (!(backupEntity && backupEntity->session)) {
479         HILOGE("Failed to get backupSession entity.");
480         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
481         return nullptr;
482     }
483     auto cbExec = [session{ backupEntity->session.get() }, bundles{ backupBundles },
484         infos{ bundleInfos }]() -> NError {
485         if (!session) {
486             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
487         }
488         if (!infos.empty()) {
489             return NError(session->AppendBundles(bundles, infos));
490         }
491         return NError(session->AppendBundles(bundles));
492     };
493     auto cbCompl = [](napi_env env, NError err) -> NVal {
494         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
495     };
496     NVal thisVar(env, funcArg.GetThisVar());
497     if (funcArg.GetArgc() == NARG_CNT::ONE) {
498         return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
499     } else if (!bundleInfos.empty()) {
500         return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
501     } else {
502         NVal cb(env, funcArg[NARG_POS::SECOND]);
503         return NAsyncWorkCallback(env, thisVar, cb).Schedule(className, cbExec, cbCompl).val_;
504     }
505 }
506 
Release(napi_env env,napi_callback_info cbinfo)507 napi_value SessionIncrementalBackupNExporter::Release(napi_env env, napi_callback_info cbinfo)
508 {
509     HILOGD("called SessionIncrementalBackup::Release begin");
510     if (!SAUtils::CheckBackupPermission()) {
511         HILOGE("Has not permission!");
512         NError(E_PERMISSION).ThrowErr(env);
513         return nullptr;
514     }
515     if (!SAUtils::IsSystemApp()) {
516         HILOGE("System App check fail!");
517         NError(E_PERMISSION_SYS).ThrowErr(env);
518         return nullptr;
519     }
520     NFuncArg funcArg(env, cbinfo);
521     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
522         HILOGE("Number of arguments unmatched.");
523         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
524         return nullptr;
525     }
526 
527     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
528     if (!(backupEntity && backupEntity->session)) {
529         HILOGE("Failed to get backupSession entity.");
530         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
531         return nullptr;
532     }
533 
534     auto cbExec = [session {backupEntity->session.get()}]() -> NError {
535         if (!session) {
536             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
537         }
538         return NError(session->Release());
539     };
540     auto cbCompl = [](napi_env env, NError err) -> NVal {
541         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
542     };
543 
544     HILOGD("Called SessionIncrementalBackup::Release end.");
545 
546     NVal thisVar(env, funcArg.GetThisVar());
547     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
548 }
549 
Export()550 bool SessionIncrementalBackupNExporter::Export()
551 {
552     HILOGD("called SessionIncrementalBackupNExporter::Export begin");
553     vector<napi_property_descriptor> props = {
554         NVal::DeclareNapiFunction("appendBundles", AppendBundles),
555         NVal::DeclareNapiFunction("release", Release),
556     };
557 
558     auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props));
559     if (!succ) {
560         HILOGE("Failed to define class");
561         NError(EIO).ThrowErr(exports_.env_);
562         return false;
563     }
564     succ = NClass::SaveClass(exports_.env_, className, classValue);
565     if (!succ) {
566         HILOGE("Failed to save class");
567         NError(EIO).ThrowErr(exports_.env_);
568         return false;
569     }
570 
571     HILOGD("called SessionIncrementalBackupNExporter::Export end");
572     return exports_.AddProp(className, classValue);
573 }
574 
GetClassName()575 string SessionIncrementalBackupNExporter::GetClassName()
576 {
577     return SessionIncrementalBackupNExporter::className;
578 }
579 
SessionIncrementalBackupNExporter(napi_env env,napi_value exports)580 SessionIncrementalBackupNExporter::SessionIncrementalBackupNExporter(napi_env env, napi_value exports)
581     : NExporter(env, exports) {}
582 
~SessionIncrementalBackupNExporter()583 SessionIncrementalBackupNExporter::~SessionIncrementalBackupNExporter() {}
584 } // namespace OHOS::FileManagement::Backup