• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "parse_inc_info_from_js.h"
32 #include "service_proxy.h"
33 
34 namespace OHOS::FileManagement::Backup {
35 using namespace std;
36 using namespace LibN;
37 
38 struct BackupEntity {
39     unique_ptr<BIncrementalBackupSession> session;
40     shared_ptr<GeneralCallbacks> callbacks;
41 };
42 
OnFileReady(weak_ptr<GeneralCallbacks> pCallbacks,const BFileInfo & fileInfo,UniqueFd fd,UniqueFd manifestFd,int sysErrno)43 static void OnFileReady(weak_ptr<GeneralCallbacks> pCallbacks, const BFileInfo &fileInfo, UniqueFd fd,
44     UniqueFd manifestFd, int sysErrno)
45 {
46     auto callbacks = pCallbacks.lock();
47     if (!callbacks) {
48         HILOGI("callback function onFileReady has already been released");
49         return;
50     }
51     if (!bool(callbacks->onFileReady)) {
52         HILOGI("callback function onFileReady is undefined");
53         return;
54     }
55     ErrCode errCode = BError::GetCodeByErrno(sysErrno);
56     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, "system errno: " + to_string(sysErrno));
57     HILOGI("callback function incre backup onFileReady begin errCode: %{public}d, bundle: %{public}s, file: %{public}s",
58         std::get<0>(errInfo), fileInfo.owner.c_str(), GetAnonyPath(fileInfo.fileName).c_str());
59     auto cbCompl = [bundleName {fileInfo.owner}, fileName {fileInfo.fileName},
60                     fd {make_shared<UniqueFd>(fd.Release())}, manifestFd {make_shared<UniqueFd>(manifestFd.Release())},
61                     errInfo](napi_env env, NError err) -> NVal {
62         if (err) {
63             return {env, err.GetNapiErr(env)};
64         }
65         HILOGI("callback function incre backup onFileReady errCode: %{public}d, bundle: %{public}s, file: %{public}s",
66             std::get<0>(errInfo), bundleName.c_str(), GetAnonyPath(fileName).c_str());
67         NVal obj;
68         ErrParam errorParam = [ errInfo ]() {
69             return errInfo;
70         };
71         if (std::get<0>(errInfo) != 0) {
72             obj = NVal {env, NError(errorParam).GetNapiErr(env)};
73             napi_status status = napi_set_named_property(env, obj.val_, FILEIO_TAG_ERR_DATA.c_str(),
74                 NVal::CreateUTF8String(env, bundleName).val_);
75             if (status != napi_ok) {
76                 HILOGE("Failed to set data, status %{public}d, bundleName %{public}s", status, bundleName.c_str());
77             }
78         } else {
79             obj = NVal::CreateObject(env);
80             obj.AddProp({
81                 NVal::DeclareNapiProperty(BConstants::BUNDLE_NAME.c_str(),
82                     NVal::CreateUTF8String(env, bundleName).val_),
83                 NVal::DeclareNapiProperty(BConstants::URI.c_str(), NVal::CreateUTF8String(env, fileName).val_),
84                 NVal::DeclareNapiProperty(BConstants::FD.c_str(), NVal::CreateInt32(env, fd->Release()).val_),
85                 NVal::DeclareNapiProperty(BConstants::MANIFEST_FD.c_str(),
86                     NVal::CreateInt32(env, manifestFd->Release()).val_)});
87         }
88         HILOGI("callback function incre backup onFileReady end errCode:%{public}d, bundle:%{public}s, file:%{public}s",
89             std::get<0>(errInfo), bundleName.c_str(), GetAnonyPath(fileName).c_str());
90         return {obj};
91     };
92 
93     callbacks->onFileReady.ThreadSafeSchedule(cbCompl);
94 }
95 
onBundleBegin(weak_ptr<GeneralCallbacks> pCallbacks,ErrCode err,const BundleName name)96 static void onBundleBegin(weak_ptr<GeneralCallbacks> pCallbacks, ErrCode err, const BundleName name)
97 {
98     HILOGI("Callback onBundleBegin, bundleName=%{public}s, errCode=%{public}d", name.c_str(), err);
99     auto callbacks = pCallbacks.lock();
100     if (!callbacks) {
101         HILOGI("callback function onBundleBegin has already been released");
102         return;
103     }
104     if (!bool(callbacks->onBundleBegin)) {
105         HILOGI("callback function onBundleBegin is undefined");
106         return;
107     }
108 
109     ErrCode errCode = BError::GetBackupCodeByErrno(err);
110     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
111     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
112     HILOGI("callback function incremental backup onBundleBegin start errCode: %{public}d", std::get<0>(errInfo));
113     auto cbCompl = [name {name}, errCode {err}, errInfo](napi_env env, NError err) -> NVal {
114         NVal bundleName = NVal::CreateUTF8String(env, name);
115         if (!err && errCode == 0) {
116             return bundleName;
117         }
118         ErrParam errorParam = [ errInfo ]() {
119             return errInfo;
120         };
121         NVal res;
122         if (err) {
123             res = NVal {env, err.GetNapiErr(env)};
124         } else {
125             res = NVal {env, NError(errorParam).GetNapiErr(env)};
126         }
127         napi_status status = napi_set_named_property(env, res.val_, FILEIO_TAG_ERR_DATA.c_str(), bundleName.val_);
128         if (status != napi_ok) {
129             HILOGE("Failed to set data property, status %{public}d, bundleName %{public}s", status, name.c_str());
130         }
131         HILOGI("callback function incremental backup onBundleBegin end errCode: %{public}d", std::get<0>(errInfo));
132         return res;
133     };
134 
135     callbacks->onBundleBegin.ThreadSafeSchedule(cbCompl);
136 }
137 
onBundleEnd(weak_ptr<GeneralCallbacks> pCallbacks,ErrCode err,const BundleName name)138 static void onBundleEnd(weak_ptr<GeneralCallbacks> pCallbacks, ErrCode err, const BundleName name)
139 {
140     HILOGI("Callback onBundleEnd, bundleName=%{public}s, errCode=%{public}d", name.c_str(), err);
141     auto callbacks = pCallbacks.lock();
142     if (!callbacks) {
143         HILOGI("callback function onBundleEnd has already been released");
144         return;
145     }
146     if (!bool(callbacks->onBundleEnd)) {
147         HILOGI("callback function onBundleEnd is undefined");
148         return;
149     }
150 
151     ErrCode errCode = BError::GetBackupCodeByErrno(err);
152     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
153     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
154     HILOGI("callback function incremental backup onBundleEnd start errCode: %{public}d", std::get<0>(errInfo));
155     auto cbCompl = [name {name}, errCode {err}, errInfo](napi_env env, NError err) -> NVal {
156         NVal bundleName = NVal::CreateUTF8String(env, name);
157         if (!err && errCode == 0) {
158             return bundleName;
159         }
160         ErrParam errorParam = [ errInfo ]() {
161             return errInfo;
162         };
163         NVal res;
164         if (err) {
165             res = NVal {env, err.GetNapiErr(env)};
166         } else {
167             res = NVal {env, NError(errorParam).GetNapiErr(env)};
168         }
169         napi_status status = napi_set_named_property(env, res.val_, FILEIO_TAG_ERR_DATA.c_str(), bundleName.val_);
170         if (status != napi_ok) {
171             HILOGE("Failed to set data property, status %{public}d, bundleName %{public}s", status, name.c_str());
172         }
173         HILOGI("callback function incremental backup onBundleBegin end errCode: %{public}d", std::get<0>(errInfo));
174         return res;
175     };
176 
177     callbacks->onBundleEnd.ThreadSafeSchedule(cbCompl);
178 }
179 
onAllBundlesEnd(weak_ptr<GeneralCallbacks> pCallbacks,ErrCode err)180 static void onAllBundlesEnd(weak_ptr<GeneralCallbacks> pCallbacks, ErrCode err)
181 {
182     auto callbacks = pCallbacks.lock();
183     if (!callbacks) {
184         HILOGI("callback function onAllBundlesEnd has already been released");
185         return;
186     }
187     if (!bool(callbacks->onAllBundlesEnd)) {
188         HILOGI("callback function onAllBundlesEnd is undefined");
189         return;
190     }
191 
192     ErrCode errCode = BError::GetBackupCodeByErrno(err);
193     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
194     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
195     HILOGI("callback function incremental backup onAllBundlesEnd begin errCode: %{public}d", std::get<0>(errInfo));
196     auto cbCompl = [errCode {err}, errInfo](napi_env env, NError err) -> NVal {
197         if (!err && errCode == 0) {
198             return NVal::CreateUndefined(env);
199         }
200         ErrParam errorParam = [ errInfo ]() {
201             return errInfo;
202         };
203         NVal res;
204         if (err) {
205             res = NVal {env, err.GetNapiErr(env)};
206         } else {
207             res = NVal {env, NError(errorParam).GetNapiErr(env)};
208         }
209         HILOGI("callback function incremental backup onAllBundlesEnd end errCode: %{public}d", std::get<0>(errInfo));
210         return res;
211     };
212 
213     callbacks->onAllBundlesEnd.ThreadSafeSchedule(cbCompl);
214 }
215 
OnResultReport(weak_ptr<GeneralCallbacks> pCallbacks,const std::string bundleName,const std::string result)216 static void OnResultReport(weak_ptr<GeneralCallbacks> pCallbacks, const std::string bundleName,
217     const std::string result)
218 {
219     HILOGI("Callback OnResultReport, bundleName=%{public}s", bundleName.c_str());
220     auto callbacks = pCallbacks.lock();
221     if (!callbacks) {
222         HILOGI("callback function onResultReport has already been released");
223         return;
224     }
225     if (!bool(callbacks->onResultReport)) {
226         HILOGI("callback function onResultReport is undefined");
227         return;
228     }
229     auto cbCompl = [bName {bundleName}, res {result}](napi_env env, vector<napi_value> &argv) -> bool {
230         napi_value napi_bName = nullptr;
231         if (napi_create_string_utf8(env, bName.c_str(), bName.size(), &napi_bName) != napi_ok) {
232             HILOGE("create napi string failed");
233             return false;
234         }
235         argv.emplace_back(napi_bName);
236         napi_value napi_res = nullptr;
237         if (napi_create_string_utf8(env, res.c_str(), res.size(), &napi_res) != napi_ok) {
238             HILOGE("create napi string failed");
239             return false;
240         }
241         argv.emplace_back(napi_res);
242         return true;
243     };
244     callbacks->onResultReport.CallJsMethod(cbCompl);
245 }
246 
OnBackupServiceDied(weak_ptr<GeneralCallbacks> pCallbacks)247 static void OnBackupServiceDied(weak_ptr<GeneralCallbacks> pCallbacks)
248 {
249     HILOGI("Callback OnBackupServiceDied.");
250     auto callbacks = pCallbacks.lock();
251     if (!callbacks) {
252         HILOGI("js callback function onBackupServiceDied has already been released");
253         return;
254     }
255     if (!bool(callbacks->onBackupServiceDied)) {
256         HILOGI("callback function onBackupServiceDied is undefined");
257         return;
258     }
259 
260     auto cbCompl = [](napi_env env, vector<napi_value> &argv) -> bool {
261         argv.emplace_back(nullptr);
262         napi_value napi_res = nullptr;
263         if (napi_get_undefined(env, &napi_res) != napi_ok) {
264             HILOGE("create undefined napi object failed");
265             return false;
266         }
267         argv.emplace_back(napi_res);
268         return true;
269     };
270     callbacks->onBackupServiceDied.CallJsMethod(cbCompl);
271 }
272 
OnProcess(weak_ptr<GeneralCallbacks> pCallbacks,const BundleName name,const std::string processInfo)273 static void OnProcess(weak_ptr<GeneralCallbacks> pCallbacks, const BundleName name, const std::string processInfo)
274 {
275     HILOGI("Callback OnProcess, bundleName=%{public}s", name.c_str());
276     auto callbacks = pCallbacks.lock();
277     if (!callbacks) {
278         HILOGI("callback function OnProcess has already been released");
279         return;
280     }
281     if (!bool(callbacks->onProcess)) {
282         HILOGI("callback function OnProcess is undefined");
283         return;
284     }
285     auto cbCompl = [bundleName {name}, process {processInfo}](napi_env env, vector<napi_value> &argv) -> bool {
286         napi_value napi_bName = nullptr;
287         if (napi_create_string_utf8(env, bundleName.c_str(), bundleName.size(), &napi_bName) != napi_ok) {
288             HILOGE("create napi string failed");
289             return false;
290         }
291         argv.emplace_back(napi_bName);
292         napi_value napi_process = nullptr;
293         if (napi_create_string_utf8(env, process.c_str(), process.size(), &napi_process) != napi_ok) {
294             HILOGE("create napi string failed");
295             return false;
296         }
297         argv.emplace_back(napi_process);
298         return true;
299     };
300     callbacks->onProcess.CallJsMethod(cbCompl);
301 }
302 
SetIncrementalBackupEntity(napi_env env,NFuncArg & funcArg,std::unique_ptr<BackupEntity> backupEntity)303 static bool SetIncrementalBackupEntity(napi_env env, NFuncArg &funcArg, std::unique_ptr<BackupEntity> backupEntity)
304 {
305     auto finalize = [](napi_env env, void *data, void *hint) {
306         std::unique_ptr<BackupEntity> entity = std::unique_ptr<BackupEntity>(static_cast<BackupEntity *>(data));
307         if (entity == nullptr) {
308             HILOGE("Entity is nullptr");
309             return;
310         }
311         if (entity->callbacks == nullptr) {
312             HILOGE("Callbacks is nullptr");
313             return;
314         }
315         entity->callbacks->RemoveCallbackRef();
316     };
317     if (napi_wrap(env, funcArg.GetThisVar(), backupEntity.release(), finalize, nullptr, nullptr) != napi_ok) {
318         HILOGE("Failed to set BackupEntity entity.");
319         return false;
320     }
321     return true;
322 }
323 
OnBackupSizeReport(weak_ptr<GeneralCallbacks> pCallbacks,const std::string scannedResult)324 static void OnBackupSizeReport(weak_ptr<GeneralCallbacks> pCallbacks, const std::string scannedResult)
325 {
326     HILOGI("Callback OnBackupSizeReport...");
327     auto callbacks = pCallbacks.lock();
328     if (!callbacks) {
329         HILOGE("callback function OnScanning has already been released");
330         return;
331     }
332     if (!bool(callbacks->onBackupSizeReport)) {
333         HILOGE("callback function OnScanning is undefined");
334         return;
335     }
336     auto cbCompl = [scannedInfo {scannedResult}](napi_env env, vector<napi_value> &argv) -> bool {
337         napi_value napi_scanned = nullptr;
338         if (napi_create_string_utf8(env, scannedInfo.c_str(), scannedInfo.size(), &napi_scanned) != napi_ok) {
339             HILOGE("create napi string failed");
340             return false;
341         }
342         argv.push_back(napi_scanned);
343         return true;
344     };
345     callbacks->onBackupSizeReport.CallJsMethod(cbCompl);
346 }
347 
Constructor(napi_env env,napi_callback_info cbinfo)348 napi_value SessionIncrementalBackupNExporter::Constructor(napi_env env, napi_callback_info cbinfo)
349 {
350     HILOGD("called SessionIncrementalBackup::Constructor begin");
351     if (!SAUtils::CheckBackupPermission()) {
352         NError(E_PERMISSION).ThrowErr(env);
353         return nullptr;
354     }
355     if (!SAUtils::IsSystemApp()) {
356         NError(E_PERMISSION_SYS).ThrowErr(env);
357         return nullptr;
358     }
359     NFuncArg funcArg(env, cbinfo);
360     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
361         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
362         return nullptr;
363     }
364     NVal callbacks(env, funcArg[NARG_POS::FIRST]);
365     if (!callbacks.TypeIs(napi_object)) {
366         NError(BError(BError::Codes::SDK_INVAL_ARG, "First argument is not an object.").GetCode()).ThrowErr(env);
367         return nullptr;
368     }
369     NVal ptr(env, funcArg.GetThisVar());
370     auto backupEntity = std::make_unique<BackupEntity>();
371     backupEntity->callbacks = make_shared<GeneralCallbacks>(env, ptr, callbacks);
372     ErrCode errCode;
373     std::string errMsg;
374     backupEntity->session = BIncrementalBackupSession::Init(BIncrementalBackupSession::Callbacks {
375         .onFileReady = bind(OnFileReady, backupEntity->callbacks, placeholders::_1, placeholders::_2, placeholders::_3,
376             placeholders::_4),
377         .onBundleStarted = bind(onBundleBegin, backupEntity->callbacks, placeholders::_1, placeholders::_2),
378         .onBundleFinished = bind(onBundleEnd, backupEntity->callbacks, placeholders::_1, placeholders::_2),
379         .onAllBundlesFinished = bind(onAllBundlesEnd, backupEntity->callbacks, placeholders::_1),
380         .onResultReport = bind(OnResultReport, backupEntity->callbacks, placeholders::_1, placeholders::_2),
381         .onBackupServiceDied = bind(OnBackupServiceDied, backupEntity->callbacks),
382         .onProcess = bind(OnProcess, backupEntity->callbacks, placeholders::_1, placeholders::_2),
383         .onBackupSizeReport = bind(OnBackupSizeReport, backupEntity->callbacks, placeholders::_1)}, errMsg, errCode);
384     if (!backupEntity->session) {
385         std::tuple<uint32_t, std::string> errInfo =
386             std::make_tuple(errCode, BError::GetBackupMsgByErrno(errCode) + ", " + errMsg);
387         ErrParam errorParam = [ errInfo ]() { return errInfo;};
388         NError(errorParam).ThrowErr(env);
389         return nullptr;
390     }
391     if (!SetIncrementalBackupEntity(env, funcArg, std::move(backupEntity))) {
392         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to set BackupEntity entity.").GetCode()).ThrowErr(env);
393         return nullptr;
394     }
395     HILOGD("called SessionIncrementalBackup::Constructor end");
396     return funcArg.GetThisVar();
397 }
398 
GetLocalCapabilities(napi_env env,napi_callback_info cbinfo)399 napi_value SessionIncrementalBackupNExporter::GetLocalCapabilities(napi_env env, napi_callback_info cbinfo)
400 {
401     HILOGI("called SessionBackup, GetLocalCapabilities Begin");
402     if (!SAUtils::CheckBackupPermission()) {
403         HILOGE("Has not permission!");
404         NError(E_PERMISSION).ThrowErr(env);
405         return nullptr;
406     }
407     if (!SAUtils::IsSystemApp()) {
408         HILOGE("System App check fail!");
409         NError(E_PERMISSION_SYS).ThrowErr(env);
410         return nullptr;
411     }
412     NFuncArg funcArg(env, cbinfo);
413     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
414         HILOGE("Number of arguments unmatched.");
415         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
416         return nullptr;
417     }
418     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
419     if (!(backupEntity && backupEntity->session)) {
420         HILOGE("Failed to get backupSession entity.");
421         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
422         return nullptr;
423     }
424     UniqueFd fd;
425     auto cbExec = [session {backupEntity->session.get()}, &fd]() -> NError {
426         if (!session) {
427             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
428         }
429         fd = session->GetLocalCapabilities();
430         return fd < 0 ? NError(BError(BError::Codes::SA_INVAL_ARG, "Failed to get local capabilities.").GetCode()) :
431             NError(BError(BError::Codes::OK, "Success to get local capabilities.").GetCode());
432     };
433     auto cbCompl = [&fd](napi_env env, NError err) -> NVal {
434         NVal obj = NVal::CreateObject(env);
435         obj.AddProp({NVal::DeclareNapiProperty(BConstants::FD.c_str(), NVal::CreateInt32(env, fd.Release()).val_)});
436         return err ? NVal {env, err.GetNapiErr(env)} : obj;
437     };
438     NVal thisVar(env, funcArg.GetThisVar());
439     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
440 }
441 
GetBackupDataSize(napi_env env,napi_callback_info cbinfo)442 napi_value SessionIncrementalBackupNExporter::GetBackupDataSize(napi_env env, napi_callback_info cbinfo)
443 {
444     HILOGI("called GetBackupDataSize Begin");
445     if (!SAUtils::CheckBackupPermission()) {
446         HILOGE("Has no permission!");
447         NError(E_PERMISSION).ThrowErr(env);
448         return nullptr;
449     }
450     if (!SAUtils::IsSystemApp()) {
451         HILOGE("System app check failed!");
452         NError(E_PERMISSION_SYS).ThrowErr(env);
453         return nullptr;
454     }
455     NFuncArg funcArg(env, cbinfo);
456     std::vector<BIncrementalData> bundleNames;
457     bool isPreciseScan;
458     if (!Parse::VerifyAndParseParams(env, funcArg, isPreciseScan, bundleNames)) {
459         HILOGE("VerifyAndParseParams failed");
460         return nullptr;
461     }
462     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
463     if (!(backupEntity && backupEntity->session)) {
464         HILOGE("Failed to get backupSession entity.");
465         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
466         return nullptr;
467     }
468     auto cbExec = [session {backupEntity->session.get()}, isPreciseScan {isPreciseScan},
469         bundleNames {move(bundleNames)}]() -> NError {
470         if (!session) {
471             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
472         }
473         auto ret = session->GetBackupDataSize(isPreciseScan, bundleNames);
474         if (ret != ERR_OK) {
475             return NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to GetBackupDataSize").GetCode());
476         }
477         HILOGI("GetBackupDataSize end");
478         return NError(ERRNO_NOERR);
479     };
480     auto cbCompl = [](napi_env env, NError err) -> NVal {
481         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
482     };
483     NVal thisVar(env, funcArg.GetThisVar());
484     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
485 }
486 
VerifyParamSuccess(NFuncArg & funcArg,std::vector<BIncrementalData> & backupBundles,std::vector<std::string> & bundleInfos,napi_env env)487 static bool VerifyParamSuccess(NFuncArg &funcArg, std::vector<BIncrementalData> &backupBundles,
488     std::vector<std::string> &bundleInfos, napi_env env)
489 {
490     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
491         HILOGE("Number of arguments unmatched.");
492         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
493         return false;
494     }
495     auto [succ, bundles] = Parse::ParseDataList(env, funcArg[NARG_POS::FIRST]);
496     if (!succ) {
497         HILOGE("bundles array invalid.");
498         NError(BError(BError::Codes::SDK_INVAL_ARG, "bundles array invalid.").GetCode()).ThrowErr(env);
499         return false;
500     }
501     backupBundles = bundles;
502     NVal jsInfos(env, funcArg[NARG_POS::SECOND]);
503     if (jsInfos.TypeIs(napi_undefined) || jsInfos.TypeIs(napi_null)) {
504         HILOGW("Third param is not exist");
505         return true;
506     }
507     auto [deSuc, jsBundleInfos, deIgnore] = jsInfos.ToStringArray();
508     if (deSuc) {
509         bundleInfos = jsBundleInfos;
510         if (backupBundles.size() != bundleInfos.size()) {
511             HILOGE("backupBundles count is not equals bundleInfos count");
512             return false;
513         }
514         return true;
515     }
516     HILOGI("Second param is callback");
517     return true;
518 }
519 
AppendBundles(napi_env env,napi_callback_info cbinfo)520 napi_value SessionIncrementalBackupNExporter::AppendBundles(napi_env env, napi_callback_info cbinfo)
521 {
522     HILOGD("called SessionIncrementalBackup::AppendBundles begin");
523     if (!SAUtils::CheckBackupPermission()) {
524         HILOGE("Has not permission!");
525         NError(E_PERMISSION).ThrowErr(env);
526         return nullptr;
527     }
528     if (!SAUtils::IsSystemApp()) {
529         HILOGE("System App check fail!");
530         NError(E_PERMISSION_SYS).ThrowErr(env);
531         return nullptr;
532     }
533     std::vector<BIncrementalData> backupBundles;
534     std::vector<std::string> bundleInfos;
535     NFuncArg funcArg(env, cbinfo);
536     if (!VerifyParamSuccess(funcArg, backupBundles, bundleInfos, env)) {
537         HILOGE("VerifyParamSuccess fail");
538         return nullptr;
539     }
540     auto backupEntity = NClass::GetEntityOf<BackupEntity>(env, funcArg.GetThisVar());
541     if (!(backupEntity && backupEntity->session)) {
542         HILOGE("Failed to get backupSession entity.");
543         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get backupSession entity.").GetCode()).ThrowErr(env);
544         return nullptr;
545     }
546     auto cbExec = [session{ backupEntity->session.get() }, bundles{ backupBundles },
547         infos{ bundleInfos }]() -> NError {
548         if (!session) {
549             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
550         }
551         if (!infos.empty()) {
552             return NError(session->AppendBundles(bundles, infos));
553         }
554         return NError(session->AppendBundles(bundles));
555     };
556     auto cbCompl = [](napi_env env, NError err) -> NVal {
557         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
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 SessionIncrementalBackupNExporter::Release(napi_env env, napi_callback_info cbinfo)
571 {
572     HILOGD("called SessionIncrementalBackup::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 SessionIncrementalBackup::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 SessionIncrementalBackupNExporter::Cancel(napi_env env, napi_callback_info info)
614 {
615     HILOGI("Called SessionIncrementalBackup::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 
Export()658 bool SessionIncrementalBackupNExporter::Export()
659 {
660     HILOGD("called SessionIncrementalBackupNExporter::Export begin");
661     vector<napi_property_descriptor> props = {
662         NVal::DeclareNapiFunction("getLocalCapabilities", GetLocalCapabilities),
663         NVal::DeclareNapiFunction("getBackupDataSize", GetBackupDataSize),
664         NVal::DeclareNapiFunction("appendBundles", AppendBundles),
665         NVal::DeclareNapiFunction("release", Release),
666         NVal::DeclareNapiFunction("cancel", Cancel),
667     };
668 
669     auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props));
670     if (!succ) {
671         HILOGE("Failed to define class");
672         NError(EIO).ThrowErr(exports_.env_);
673         return false;
674     }
675     succ = NClass::SaveClass(exports_.env_, className, classValue);
676     if (!succ) {
677         HILOGE("Failed to save class");
678         NError(EIO).ThrowErr(exports_.env_);
679         return false;
680     }
681 
682     HILOGD("called SessionIncrementalBackupNExporter::Export end");
683     return exports_.AddProp(className, classValue);
684 }
685 
GetClassName()686 string SessionIncrementalBackupNExporter::GetClassName()
687 {
688     return SessionIncrementalBackupNExporter::className;
689 }
690 
SessionIncrementalBackupNExporter(napi_env env,napi_value exports)691 SessionIncrementalBackupNExporter::SessionIncrementalBackupNExporter(napi_env env, napi_value exports)
692     : NExporter(env, exports) {}
693 
~SessionIncrementalBackupNExporter()694 SessionIncrementalBackupNExporter::~SessionIncrementalBackupNExporter() {}
695 } // namespace OHOS::FileManagement::Backup