• 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_restore_n_exporter.h"
16 
17 #include <functional>
18 #include <memory>
19 #include <fcntl.h>
20 
21 #include "b_error/b_error.h"
22 #include "b_filesystem/b_dir.h"
23 #include "b_filesystem/b_file.h"
24 #include "b_incremental_restore_session.h"
25 #include "b_ohos/startup/backup_para.h"
26 #include "b_resources/b_constants.h"
27 #include "b_sa/b_sa_utils.h"
28 #include "b_session_restore.h"
29 #include "backup_kit_inner.h"
30 #include "filemgmt_libhilog.h"
31 #include "general_callbacks.h"
32 #include "service_proxy.h"
33 
34 namespace OHOS::FileManagement::Backup {
35 using namespace std;
36 using namespace LibN;
37 
38 struct RestoreEntity {
39     unique_ptr<BSessionRestore> sessionWhole;
40     unique_ptr<BIncrementalRestoreSession> sessionSheet;
41     shared_ptr<GeneralCallbacks> callbacks;
42 };
43 
OnFileReadySheet(weak_ptr<GeneralCallbacks> pCallbacks,const BFileInfo & fileInfo,UniqueFd fd,UniqueFd manifestFd,int32_t sysErrno)44 static void OnFileReadySheet(weak_ptr<GeneralCallbacks> pCallbacks, const BFileInfo &fileInfo,
45     UniqueFd fd, UniqueFd manifestFd, int32_t sysErrno)
46 {
47     auto callbacks = pCallbacks.lock();
48     if (!callbacks) {
49         HILOGI("callback function onFileReady has already been released");
50         return;
51     }
52     if (!bool(callbacks->onFileReady)) {
53         HILOGI("callback function onFileReady is undefined");
54         return;
55     }
56     ErrCode errCode = BError::GetCodeByErrno(sysErrno);
57     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, "system errno: " + to_string(sysErrno));
58     HILOGI("callback function restore onFileReadySheet begin errCode: %{public}d, bundle: %{public}s, file: %{public}s",
59         std::get<0>(errInfo), fileInfo.owner.c_str(), GetAnonyPath(fileInfo.fileName).c_str());
60     auto cbCompl = [bundleName {fileInfo.owner}, fileName {fileInfo.fileName},
61                     fd {make_shared<UniqueFd>(fd.Release())}, manifestFd {make_shared<UniqueFd>(manifestFd.Release())},
62                     errInfo](napi_env env, NError err) -> NVal {
63         if (err) {
64             return {env, err.GetNapiErr(env)};
65         }
66         HILOGI("callback function restore OnFileReadySheet errCode: %{public}d, bundle: %{public}s, file: %{public}s",
67             std::get<0>(errInfo), bundleName.c_str(), GetAnonyPath(fileName).c_str());
68         NVal obj;
69         ErrParam errorParam = [ errInfo ]() {
70             return errInfo;
71         };
72         if (std::get<0>(errInfo) != 0) {
73             obj = NVal {env, NError(errorParam).GetNapiErr(env)};
74             napi_status status = napi_set_named_property(env, obj.val_, FILEIO_TAG_ERR_DATA.c_str(),
75                 NVal::CreateUTF8String(env, bundleName).val_);
76             if (status != napi_ok) {
77                 HILOGE("Failed to set data, status %{public}d, bundleName %{public}s", status, bundleName.c_str());
78             }
79         } else {
80             obj = NVal::CreateObject(env);
81             obj.AddProp({
82                 NVal::DeclareNapiProperty(BConstants::BUNDLE_NAME.c_str(),
83                     NVal::CreateUTF8String(env, bundleName).val_),
84                 NVal::DeclareNapiProperty(BConstants::URI.c_str(), NVal::CreateUTF8String(env, fileName).val_),
85                 NVal::DeclareNapiProperty(BConstants::FD.c_str(), NVal::CreateInt32(env, fd->Release()).val_),
86                 NVal::DeclareNapiProperty(BConstants::MANIFEST_FD.c_str(),
87                     NVal::CreateInt32(env, manifestFd->Release()).val_)});
88         }
89         HILOGI("callback function restore onFileReadySheet end errCode:%{public}d, bundle:%{public}s, file:%{public}s",
90             std::get<0>(errInfo), bundleName.c_str(), GetAnonyPath(fileName).c_str());
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     auto callbacks = pCallbacks.lock();
101     if (!callbacks) {
102         HILOGI("callback function onBundleBegin has already been released");
103         return;
104     }
105     if (!bool(callbacks->onBundleBegin)) {
106         HILOGI("callback function onBundleBegin is undefined");
107         return;
108     }
109 
110     ErrCode errCode = BError::GetBackupCodeByErrno(err);
111     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
112     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
113     HILOGI("callback function restore onBundleBegin start errCode: %{public}d", std::get<0>(errInfo));
114     auto cbCompl = [name {name}, errCode {err}, errInfo](napi_env env, NError err) -> NVal {
115         NVal bundleName = NVal::CreateUTF8String(env, name);
116         if (!err && errCode == 0) {
117             return bundleName;
118         }
119         ErrParam errorParam = [ errInfo ]() {
120             return errInfo;
121         };
122         NVal res;
123         if (err) {
124             res = NVal {env, err.GetNapiErr(env)};
125         } else {
126             res = NVal {env, NError(errorParam).GetNapiErr(env)};
127         }
128         napi_status status = napi_set_named_property(env, res.val_, FILEIO_TAG_ERR_DATA.c_str(), bundleName.val_);
129         if (status != napi_ok) {
130             HILOGE("Failed to set data property, status %{public}d, bundleName %{public}s", status, name.c_str());
131         }
132         HILOGI("callback function restore onBundleBegin end errCode: %{public}d", std::get<0>(errInfo));
133         return res;
134     };
135 
136     callbacks->onBundleBegin.ThreadSafeSchedule(cbCompl);
137 }
138 
onBundleEnd(weak_ptr<GeneralCallbacks> pCallbacks,ErrCode err,const BundleName name)139 static void onBundleEnd(weak_ptr<GeneralCallbacks> pCallbacks, ErrCode err, const BundleName name)
140 {
141     HILOGI("Callback onBundleEnd, bundleName=%{public}s, errCode=%{public}d", name.c_str(), err);
142     auto callbacks = pCallbacks.lock();
143     if (!callbacks) {
144         HILOGI("callback function onBundleEnd has already been released");
145         return;
146     }
147     if (!bool(callbacks->onBundleEnd)) {
148         HILOGI("callback function onBundleEnd is undefined");
149         return;
150     }
151 
152     ErrCode errCode = BError::GetBackupCodeByErrno(err);
153     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
154     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
155     HILOGI("callback function restore onBundleEnd start errCode: %{public}d", std::get<0>(errInfo));
156     auto cbCompl = [name {name}, errCode {err}, errInfo](napi_env env, NError err) -> NVal {
157         NVal bundleName = NVal::CreateUTF8String(env, name);
158         if (!err && errCode == 0) {
159             return bundleName;
160         }
161         ErrParam errorParam = [ errInfo ]() {
162             return errInfo;
163         };
164         NVal res;
165         if (err) {
166             res = NVal {env, err.GetNapiErr(env)};
167         } else {
168             res = NVal {env, NError(errorParam).GetNapiErr(env)};
169         }
170         napi_status status = napi_set_named_property(env, res.val_, FILEIO_TAG_ERR_DATA.c_str(), bundleName.val_);
171         if (status != napi_ok) {
172             HILOGE("Failed to set data property, status %{public}d, bundleName %{public}s", status, name.c_str());
173         }
174         HILOGI("callback function restore onBundleEnd end errCode: %{public}d", std::get<0>(errInfo));
175         return res;
176     };
177 
178     callbacks->onBundleEnd.ThreadSafeSchedule(cbCompl);
179 }
180 
onAllBundlesEnd(weak_ptr<GeneralCallbacks> pCallbacks,ErrCode err)181 static void onAllBundlesEnd(weak_ptr<GeneralCallbacks> pCallbacks, ErrCode err)
182 {
183     auto callbacks = pCallbacks.lock();
184     if (!callbacks) {
185         HILOGI("callback function onAllBundlesEnd has already been released");
186         return;
187     }
188     if (!bool(callbacks->onAllBundlesEnd)) {
189         HILOGI("callback function onAllBundlesEnd is undefined");
190         return;
191     }
192 
193     ErrCode errCode = BError::GetBackupCodeByErrno(err);
194     std::string errMsg = BError::GetBackupMsgByErrno(errCode) + ", origin errno: " + to_string(err);
195     std::tuple<uint32_t, std::string> errInfo = std::make_tuple(errCode, errMsg);
196     HILOGI("callback function restore onAllBundlesEnd begin errCode: %{public}d", std::get<0>(errInfo));
197     auto cbCompl = [errCode {err}, errInfo](napi_env env, NError err) -> NVal {
198         if (!err && errCode == 0) {
199             return NVal::CreateUndefined(env);
200         }
201         ErrParam errorParam = [ errInfo ]() {
202             return errInfo;
203         };
204         NVal res;
205         if (err) {
206             res = NVal {env, err.GetNapiErr(env)};
207         } else {
208             res = NVal {env, NError(errorParam).GetNapiErr(env)};
209         }
210         HILOGI("callback function backup onAllBundlesEnd end errCode: %{public}d", std::get<0>(errInfo));
211         return res;
212     };
213 
214     callbacks->onAllBundlesEnd.ThreadSafeSchedule(cbCompl);
215 }
216 
OnBackupServiceDied(weak_ptr<GeneralCallbacks> pCallbacks)217 static void OnBackupServiceDied(weak_ptr<GeneralCallbacks> pCallbacks)
218 {
219     HILOGI("Callback OnBackupServiceDied.");
220     auto callbacks = pCallbacks.lock();
221     if (!callbacks) {
222         HILOGI("js callback function onBackupServiceDied has already been released");
223         return;
224     }
225     if (!bool(callbacks->onBackupServiceDied)) {
226         HILOGI("callback function onBackupServiceDied is undefined");
227         return;
228     }
229 
230     auto cbCompl = [](napi_env env, vector<napi_value> &argv) -> bool {
231         argv.emplace_back(nullptr);
232         napi_value napi_res = nullptr;
233         if (napi_get_undefined(env, &napi_res) != napi_ok) {
234             HILOGE("create undefined napi object failed");
235             return false;
236         }
237         argv.emplace_back(napi_res);
238         return true;
239     };
240     callbacks->onBackupServiceDied.CallJsMethod(cbCompl);
241 }
242 
OnResultReport(weak_ptr<GeneralCallbacks> pCallbacks,const std::string bundleName,const std::string result)243 static void OnResultReport(weak_ptr<GeneralCallbacks> pCallbacks, const std::string bundleName,
244     const std::string result)
245 {
246     HILOGI("Callback OnResultReport, bundleName=%{public}s", bundleName.c_str());
247     auto callbacks = pCallbacks.lock();
248     if (!callbacks) {
249         HILOGI("callback function onResultReport has already been released");
250         return;
251     }
252     if (!bool(callbacks->onResultReport)) {
253         HILOGI("callback function onResultReport is undefined");
254         return;
255     }
256     auto cbCompl = [bName {bundleName}, res {result}](napi_env env, vector<napi_value> &argv) -> bool {
257         napi_value napi_bName = nullptr;
258         if (napi_create_string_utf8(env, bName.c_str(), bName.size(), &napi_bName) != napi_ok) {
259             HILOGE("create napi string failed");
260             return false;
261         }
262         argv.emplace_back(napi_bName);
263         napi_value napi_res = nullptr;
264         if (napi_create_string_utf8(env, res.c_str(), res.size(), &napi_res) != napi_ok) {
265             HILOGE("create napi string failed");
266             return false;
267         }
268         argv.emplace_back(napi_res);
269         return true;
270     };
271     callbacks->onResultReport.CallJsMethod(cbCompl);
272 }
273 
OnProcess(weak_ptr<GeneralCallbacks> pCallbacks,const BundleName name,const std::string processInfo)274 static void OnProcess(weak_ptr<GeneralCallbacks> pCallbacks, const BundleName name, const std::string processInfo)
275 {
276     HILOGI("Callback OnProcess, bundleName=%{public}s", name.c_str());
277     auto callbacks = pCallbacks.lock();
278     if (!callbacks) {
279         HILOGI("callback function OnProcess has already been released");
280         return;
281     }
282     if (!bool(callbacks->onProcess)) {
283         HILOGI("callback function OnProcess is undefined");
284         return;
285     }
286     auto cbCompl = [bundleName {name}, process {processInfo}](napi_env env, vector<napi_value> &argv) -> bool {
287         napi_value napi_bName = nullptr;
288         if (napi_create_string_utf8(env, bundleName.c_str(), bundleName.size(), &napi_bName) != napi_ok) {
289             HILOGE("create napi string failed");
290             return false;
291         }
292         argv.emplace_back(napi_bName);
293         napi_value napi_process = nullptr;
294         if (napi_create_string_utf8(env, process.c_str(), process.size(), &napi_process) != napi_ok) {
295             HILOGE("create napi string failed");
296             return false;
297         }
298         argv.emplace_back(napi_process);
299         return true;
300     };
301     callbacks->onProcess.CallJsMethod(cbCompl);
302 }
303 
VerifyAppendBundlesParam(NFuncArg & funcArg,int32_t & fd,std::vector<std::string> & bundleNames,std::vector<std::string> & bundleInfos,napi_env env)304 static bool VerifyAppendBundlesParam(NFuncArg &funcArg, int32_t &fd, std::vector<std::string> &bundleNames,
305     std::vector<std::string> &bundleInfos, napi_env env)
306 {
307     if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
308         HILOGE("Number of arguments unmatched.");
309         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
310         return false;
311     }
312     NVal remoteCap(env, funcArg[NARG_POS::FIRST]);
313     auto [err, jsFd] = remoteCap.ToInt32();
314     if (!err) {
315         HILOGE("First argument is not remote capabilitily file number.");
316         NError(BError(BError::Codes::SDK_INVAL_ARG, "First argument is not remote capabilitily file number.").GetCode())
317             .ThrowErr(env);
318         return false;
319     }
320     fd = jsFd;
321     NVal jsBundles(env, funcArg[NARG_POS::SECOND]);
322     auto [succ, jsBundleNames, ignore] = jsBundles.ToStringArray();
323     if (!succ) {
324         HILOGE("First argument is not bundles array.");
325         NError(BError(BError::Codes::SDK_INVAL_ARG, "First argument is not bundles array.").GetCode()).ThrowErr(env);
326         return false;
327     }
328     bundleNames = jsBundleNames;
329     NVal jsInfos(env, funcArg[NARG_POS::THIRD]);
330     if (jsInfos.TypeIs(napi_undefined) || jsInfos.TypeIs(napi_null)) {
331         HILOGW("Third param is not exist");
332         return true;
333     }
334     auto [deSuc, jsBundleInfos, deIgnore] = jsInfos.ToStringArray();
335     if (deSuc) {
336         bundleInfos = jsBundleInfos;
337         if (bundleNames.size() != bundleInfos.size()) {
338             HILOGE("bundleNames count is not equals bundleInfos count");
339             return false;
340         }
341         return true;
342     }
343     HILOGI("Third param is callback");
344     return true;
345 }
346 
ParseFileMeta(napi_env env,const NVal & fileMeta)347 static std::tuple<bool, std::unique_ptr<char[]>, std::unique_ptr<char[]>> ParseFileMeta(napi_env env,
348     const NVal &fileMeta)
349 {
350     bool succ = false;
351     std::unique_ptr<char[]> bundleName = nullptr;
352     tie(succ, bundleName, ignore) = fileMeta.GetProp(BConstants::BUNDLE_NAME).ToUTF8String();
353     if (!succ) {
354         HILOGE("First argument is not have property bundle name.");
355         return { false, nullptr, nullptr };
356     }
357 
358     std::unique_ptr<char[]> fileName = nullptr;
359     tie(succ, fileName, ignore) = fileMeta.GetProp(BConstants::URI).ToUTF8String();
360     if (!succ) {
361         HILOGE("First argument is not have property file name.");
362         return { false, nullptr, nullptr };
363     }
364 
365     return { true, move(bundleName), move(fileName) };
366 }
367 
VerifyPublishFileParam(NFuncArg & funcArg,std::string & bundleName,std::string & fileName,napi_env env)368 static bool VerifyPublishFileParam(NFuncArg &funcArg, std::string &bundleName, std::string &fileName, napi_env env)
369 {
370     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
371         HILOGE("Number of arguments unmatched.");
372         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
373         return false;
374     }
375 
376     NVal fileMeta(env, funcArg[NARG_POS::FIRST]);
377     if (!fileMeta.TypeIs(napi_object)) {
378         HILOGE("First arguments is not an object.");
379         NError(BError(BError::Codes::SDK_INVAL_ARG, "First arguments is not an object.").GetCode()).ThrowErr(env);
380         return false;
381     }
382     auto [succ, bundle, file] = ParseFileMeta(env, fileMeta);
383     if (!succ) {
384         HILOGE("ParseFileMeta failed.");
385         NError(BError(BError::Codes::SDK_INVAL_ARG, "ParseFileMeta failed.").GetCode()).ThrowErr(env);
386         return false;
387     }
388     bundleName = string(bundle.get());
389     fileName = string(file.get());
390     return true;
391 }
392 
VerifyNapiObject(napi_env env,NFuncArg & funcArg)393 static bool VerifyNapiObject(napi_env env, NFuncArg &funcArg)
394 {
395     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
396         HILOGE("Number of arguments unmatched.");
397         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
398         return true;
399     }
400     return false;
401 }
402 
VerifyNarg(napi_env env,NVal & callbacks)403 static bool VerifyNarg(napi_env env, NVal &callbacks)
404 {
405     if (!callbacks.TypeIs(napi_object)) {
406         HILOGE("First argument is not an object.");
407         NError(BError(BError::Codes::SDK_INVAL_ARG, "First argument is not an object.").GetCode()).ThrowErr(env);
408         return true;
409     }
410     return false;
411 }
412 
SetSessionRestoreEntity(napi_env env,NFuncArg & funcArg,std::unique_ptr<RestoreEntity> restoreEntity)413 static bool SetSessionRestoreEntity(napi_env env, NFuncArg &funcArg, std::unique_ptr<RestoreEntity> restoreEntity)
414 {
415     auto finalize = [](napi_env env, void *data, void *hint) {
416         std::unique_ptr<RestoreEntity> entity = std::unique_ptr<RestoreEntity>(static_cast<RestoreEntity *>(data));
417         if (entity == nullptr) {
418             HILOGE("Entity is nullptr");
419             return;
420         }
421         if (entity->callbacks == nullptr) {
422             HILOGE("Callbacks is nullptr");
423             return;
424         }
425         entity->callbacks->RemoveCallbackRef();
426     };
427     if (napi_wrap(env, funcArg.GetThisVar(), restoreEntity.release(), finalize, nullptr, nullptr) != napi_ok) {
428         HILOGE("Failed to set restoreEntity entity.");
429         return false;
430     }
431     return true;
432 }
433 
Constructor(napi_env env,napi_callback_info cbinfo)434 napi_value SessionRestoreNExporter::Constructor(napi_env env, napi_callback_info cbinfo)
435 {
436     HILOGI("called SessionRestore::Constructor begin");
437     if (!SAUtils::CheckBackupPermission()) {
438         HILOGE("Has not permission!");
439         NError(E_PERMISSION).ThrowErr(env);
440         return nullptr;
441     }
442     if (!SAUtils::IsSystemApp()) {
443         HILOGE("System App check fail!");
444         NError(E_PERMISSION_SYS).ThrowErr(env);
445         return nullptr;
446     }
447     NFuncArg funcArg(env, cbinfo);
448     if (VerifyNapiObject(env, funcArg)) {
449         return nullptr;
450     }
451     NVal callbacks(env, funcArg[NARG_POS::FIRST]);
452     if (VerifyNarg(env, callbacks)) {
453         return nullptr;
454     }
455 
456     NVal ptr(env, funcArg.GetThisVar());
457     auto restoreEntity = std::make_unique<RestoreEntity>();
458     restoreEntity->callbacks = make_shared<GeneralCallbacks>(env, ptr, callbacks);
459     restoreEntity->sessionWhole = nullptr;
460     ErrCode errCode;
461     std::string errMsg;
462     restoreEntity->sessionSheet = BIncrementalRestoreSession::Init(BIncrementalRestoreSession::Callbacks {
463         .onFileReady = bind(OnFileReadySheet, restoreEntity->callbacks, placeholders::_1, placeholders::_2,
464             placeholders::_3, placeholders::_4),
465         .onBundleStarted = bind(onBundleBegin, restoreEntity->callbacks, placeholders::_1, placeholders::_2),
466         .onBundleFinished = bind(onBundleEnd, restoreEntity->callbacks, placeholders::_1, placeholders::_2),
467         .onAllBundlesFinished = bind(onAllBundlesEnd, restoreEntity->callbacks, placeholders::_1),
468         .onResultReport = bind(OnResultReport, restoreEntity->callbacks, placeholders::_1, placeholders::_2),
469         .onBackupServiceDied = bind(OnBackupServiceDied, restoreEntity->callbacks),
470         .onProcess = bind(OnProcess, restoreEntity->callbacks, placeholders::_1, placeholders::_2)}, errMsg, errCode);
471     if (!restoreEntity->sessionSheet) {
472         std::tuple<uint32_t, std::string> errInfo = (errCode == BError(BError::Codes::SA_SESSION_CONFLICT)) ?
473             std::make_tuple(errCode, errMsg) : std::make_tuple(errCode, BError::GetBackupMsgByErrno(errCode));
474         ErrParam errorParam = [ errInfo ]() { return errInfo;};
475         NError(errorParam).ThrowErr(env);
476         return nullptr;
477     }
478     if (!SetSessionRestoreEntity(env, funcArg, std::move(restoreEntity))) {
479         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to set SessionRestore entity.").GetCode()).ThrowErr(env);
480         return nullptr;
481     }
482     HILOGI("called SessionRestore::Constructor end");
483     return funcArg.GetThisVar();
484 }
485 
GetLocalCapabilities(napi_env env,napi_callback_info cbinfo)486 napi_value SessionRestoreNExporter::GetLocalCapabilities(napi_env env, napi_callback_info cbinfo)
487 {
488     HILOGI("called SessionBackup, GetLocalCapabilities Begin");
489     if (!SAUtils::CheckBackupPermission()) {
490         HILOGE("Has not permission!");
491         NError(E_PERMISSION).ThrowErr(env);
492         return nullptr;
493     }
494     if (!SAUtils::IsSystemApp()) {
495         HILOGE("System App check fail!");
496         NError(E_PERMISSION_SYS).ThrowErr(env);
497         return nullptr;
498     }
499     NFuncArg funcArg(env, cbinfo);
500     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
501         HILOGE("Number of arguments unmatched.");
502         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
503         return nullptr;
504     }
505     auto restoreEntity = NClass::GetEntityOf<RestoreEntity>(env, funcArg.GetThisVar());
506     if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) {
507         HILOGE("Failed to get restoreSession entity.");
508         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get restoreSession entity.").GetCode()).ThrowErr(env);
509         return nullptr;
510     }
511     auto fd = make_shared<UniqueFd>();
512     auto cbExec = [session {restoreEntity}, fd]() -> NError {
513         if (!session && (session->sessionWhole || session->sessionSheet)) {
514             return NError(BError(BError::Codes::SDK_INVAL_ARG, "backup session is nullptr").GetCode());
515         }
516         if (session->sessionWhole) {
517             *fd = session->sessionWhole->GetLocalCapabilities();
518         } else if (session->sessionSheet) {
519             *fd = session->sessionSheet->GetLocalCapabilities();
520         }
521         return NError(ERRNO_NOERR);
522     };
523     auto cbCompl = [fd](napi_env env, NError err) -> NVal {
524         NVal obj = NVal::CreateObject(env);
525         obj.AddProp({NVal::DeclareNapiProperty(BConstants::FD.c_str(), NVal::CreateInt32(env, fd->Release()).val_)});
526         return {obj};
527     };
528     NVal thisVar(env, funcArg.GetThisVar());
529     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
530 }
531 
GetAppendBundlesCBExec(napi_env env,NFuncArg & funcArg,const int32_t fdRestore,const std::vector<std::string> & bundleNames,const std::vector<std::string> & bundleInfos)532 static NContextCBExec GetAppendBundlesCBExec(napi_env env, NFuncArg &funcArg, const int32_t fdRestore,
533     const std::vector<std::string> &bundleNames, const std::vector<std::string> &bundleInfos)
534 {
535     auto restoreEntity = NClass::GetEntityOf<RestoreEntity>(env, funcArg.GetThisVar());
536     if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) {
537         HILOGE("Failed to get RestoreSession entity.");
538         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get RestoreSession entity.").GetCode()).ThrowErr(env);
539         return nullptr;
540     }
541     return [entity {restoreEntity}, fd {fdRestore}, bundles {bundleNames}, infos {bundleInfos}]() -> NError {
542         if (!(entity && (entity->sessionWhole || entity->sessionSheet))) {
543             return NError(BError(BError::Codes::SDK_INVAL_ARG, "restore session is nullptr").GetCode());
544         }
545         if (fcntl(fd, F_GETFD) == -1) {
546             HILOGE("AppendBundles fd is invalid.");
547             return NError(BError(BError::Codes::SDK_INVAL_ARG, "AppendBundles fd is invalid.").GetCode());
548         }
549         if (entity->sessionWhole) {
550             if (!infos.empty()) {
551                 return NError(entity->sessionWhole->AppendBundles(UniqueFd(fd), bundles, infos));
552             }
553             return NError(entity->sessionWhole->AppendBundles(UniqueFd(fd), bundles));
554         }
555         if (!infos.empty()) {
556             return NError(entity->sessionSheet->AppendBundles(UniqueFd(fd), bundles, infos));
557         }
558         return NError(entity->sessionSheet->AppendBundles(UniqueFd(fd), bundles));
559     };
560 }
561 
AppendBundles(napi_env env,napi_callback_info cbinfo)562 napi_value SessionRestoreNExporter::AppendBundles(napi_env env, napi_callback_info cbinfo)
563 {
564     HILOGI("called SessionRestore::AppendBundles begin");
565     if (!SAUtils::CheckBackupPermission()) {
566         HILOGE("Has not permission!");
567         NError(E_PERMISSION).ThrowErr(env);
568         return nullptr;
569     }
570     if (!SAUtils::IsSystemApp()) {
571         HILOGE("System App check fail!");
572         NError(E_PERMISSION_SYS).ThrowErr(env);
573         return nullptr;
574     }
575     int32_t fdRestore = BConstants::INVALID_FD_NUM;
576     std::vector<std::string> bundleNames;
577     std::vector<std::string> bundleInfos;
578     NFuncArg funcArg(env, cbinfo);
579     if (!VerifyAppendBundlesParam(funcArg, fdRestore, bundleNames, bundleInfos, env)) {
580         return nullptr;
581     }
582     auto cbExec = GetAppendBundlesCBExec(env, funcArg, fdRestore, bundleNames, bundleInfos);
583     if (cbExec == nullptr) {
584         HILOGE("GetAppendBundlesCBExec fail!");
585         return nullptr;
586     }
587     auto cbCompl = [](napi_env env, NError err) -> NVal {
588         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
589     };
590     HILOGD("Called SessionRestore::AppendBundles end.");
591 
592     NVal thisVar(env, funcArg.GetThisVar());
593     if (funcArg.GetArgc() == NARG_CNT::TWO) {
594         return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
595     } else if (!bundleInfos.empty()) {
596         HILOGI("The third param is string array");
597         return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
598     } else {
599         HILOGI("The third param is call back");
600         NVal cb(env, funcArg[NARG_POS::THIRD]);
601         return NAsyncWorkCallback(env, thisVar, cb).Schedule(className, cbExec, cbCompl).val_;
602     }
603 }
604 
GetPublishFileCBExec(napi_env env,NFuncArg & funcArg,const std::string & bundleName,const std::string & fileName)605 static NContextCBExec GetPublishFileCBExec(napi_env env, NFuncArg &funcArg, const std::string &bundleName,
606     const std::string &fileName)
607 {
608     auto restoreEntity = NClass::GetEntityOf<RestoreEntity>(env, funcArg.GetThisVar());
609     if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) {
610         HILOGE("Failed to get RestoreSession entity.");
611         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get RestoreSession entity.").GetCode()).ThrowErr(env);
612         return nullptr;
613     }
614     return [entity {restoreEntity}, bundleName {bundleName}, fileName {fileName}]() -> NError {
615         if (!(entity && (entity->sessionWhole || entity->sessionSheet))) {
616             return NError(BError(BError::Codes::SDK_INVAL_ARG, "restore session is nullptr").GetCode());
617         }
618         BFileInfo fileInfo(bundleName, fileName, 0);
619         if (entity->sessionWhole) {
620             return NError(entity->sessionWhole->PublishFile(fileInfo));
621         }
622         if (SAUtils::IsSABundleName(bundleName)) {
623             if (SAUtils::IsSABundleName(fileName)) {
624                 HILOGI("SA %{public}s pushlish file", bundleName.c_str());
625                 if (fcntl(std::atoi(fileName.c_str()), F_GETFD) == -1) {
626                     HILOGE("PublishFile fd is invalid.");
627                     return NError(BError(BError::Codes::SDK_INVAL_ARG, "PublishFile fd is invalid.").GetCode());
628                 }
629                 return NError(entity->sessionSheet->PublishSAFile(fileInfo, UniqueFd(std::atoi(fileName.c_str()))));
630             }
631             HILOGE("SA:%{public}s, fileName:%{private}s is invalid", bundleName.c_str(), fileName.c_str());
632             return NError(BError(BError::Codes::SDK_INVAL_ARG, "PublishFile fd is invalid.").GetCode());
633         }
634         return NError(entity->sessionSheet->PublishFile(fileInfo));
635     };
636 }
637 
PublishFile(napi_env env,napi_callback_info cbinfo)638 napi_value SessionRestoreNExporter::PublishFile(napi_env env, napi_callback_info cbinfo)
639 {
640     HILOGD("called SessionRestore::PublishFile begin");
641     if (!SAUtils::CheckBackupPermission()) {
642         HILOGE("Has not permission!");
643         NError(E_PERMISSION).ThrowErr(env);
644         return nullptr;
645     }
646     if (!SAUtils::IsSystemApp()) {
647         HILOGE("System App check fail!");
648         NError(E_PERMISSION_SYS).ThrowErr(env);
649         return nullptr;
650     }
651     std::string bundleName;
652     std::string fileName;
653     NFuncArg funcArg(env, cbinfo);
654     if (!VerifyPublishFileParam(funcArg, bundleName, fileName, env)) {
655         return nullptr;
656     }
657     auto cbExec = GetPublishFileCBExec(env, funcArg, bundleName, fileName);
658     if (cbExec == nullptr) {
659         HILOGE("GetPublishFileCBExec fail!");
660         return nullptr;
661     }
662     auto cbCompl = [](napi_env env, NError err) -> NVal {
663         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
664     };
665     HILOGD("Called SessionRestore::PublishFile end.");
666 
667     NVal thisVar(env, funcArg.GetThisVar());
668     if (funcArg.GetArgc() == NARG_CNT::ONE) {
669         return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
670     } else {
671         NVal cb(env, funcArg[NARG_POS::SECOND]);
672         return NAsyncWorkCallback(env, thisVar, cb).Schedule(className, cbExec, cbCompl).val_;
673     }
674 }
675 
GetFileHandleCBExec(napi_env env,NFuncArg & funcArg,std::unique_ptr<char[]> bundleName,std::unique_ptr<char[]> fileName)676 static NContextCBExec GetFileHandleCBExec(napi_env env, NFuncArg &funcArg, std::unique_ptr<char[]> bundleName,
677     std::unique_ptr<char[]> fileName)
678 {
679     auto restoreEntity = NClass::GetEntityOf<RestoreEntity>(env, funcArg.GetThisVar());
680     if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) {
681         HILOGE("Failed to get RestoreSession entity.");
682         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get RestoreSession entity.").GetCode()).ThrowErr(env);
683         return nullptr;
684     }
685     return [entity {restoreEntity}, bundleName {string(bundleName.get())},
686         fileName {string(fileName.get())}]() -> NError {
687         if (!(entity && (entity->sessionWhole || entity->sessionSheet))) {
688             return NError(BError(BError::Codes::SDK_INVAL_ARG, "restore session is nullptr").GetCode());
689         }
690         string bundle = bundleName;
691         string file = fileName;
692         if (entity->sessionWhole) {
693             return NError(entity->sessionWhole->GetFileHandle(bundle, file));
694         }
695         return NError(entity->sessionSheet->GetFileHandle(bundle, file));
696     };
697 }
698 
GetFileHandle(napi_env env,napi_callback_info cbinfo)699 napi_value SessionRestoreNExporter::GetFileHandle(napi_env env, napi_callback_info cbinfo)
700 {
701     HILOGD("called SessionRestore::GetFileHandle begin");
702     if (!SAUtils::CheckBackupPermission()) {
703         HILOGE("Has not permission!");
704         NError(E_PERMISSION).ThrowErr(env);
705         return nullptr;
706     }
707     if (!SAUtils::IsSystemApp()) {
708         HILOGE("System App check fail!");
709         NError(E_PERMISSION_SYS).ThrowErr(env);
710         return nullptr;
711     }
712     NFuncArg funcArg(env, cbinfo);
713     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
714         HILOGE("Number of arguments unmatched.");
715         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
716         return nullptr;
717     }
718 
719     NVal fileMeta(env, funcArg[NARG_POS::FIRST]);
720     if (!fileMeta.TypeIs(napi_object)) {
721         HILOGE("First arguments is not an object.");
722         NError(BError(BError::Codes::SDK_INVAL_ARG, "First arguments is not an object.").GetCode()).ThrowErr(env);
723         return nullptr;
724     }
725 
726     auto [succ, bundleName, fileName] = ParseFileMeta(env, fileMeta);
727     if (!succ) {
728         HILOGE("ParseFileMeta failed.");
729         NError(BError(BError::Codes::SDK_INVAL_ARG, "ParseFileMeta failed.").GetCode()).ThrowErr(env);
730         return nullptr;
731     }
732 
733     auto cbExec = GetFileHandleCBExec(env, funcArg, move(bundleName), move(fileName));
734     if (cbExec == nullptr) {
735         HILOGE("GetFileHandleCBExec fail!");
736         return nullptr;
737     }
738     auto cbCompl = [](napi_env env, NError err) -> NVal {
739         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
740     };
741     HILOGD("Called SessionRestore::GetFileHandle end.");
742 
743     NVal thisVar(env, funcArg.GetThisVar());
744     if (funcArg.GetArgc() == NARG_CNT::ONE) {
745         return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
746     } else {
747         NVal cb(env, funcArg[NARG_POS::SECOND]);
748         return NAsyncWorkCallback(env, thisVar, cb).Schedule(className, cbExec, cbCompl).val_;
749     }
750 }
751 
Release(napi_env env,napi_callback_info cbinfo)752 napi_value SessionRestoreNExporter::Release(napi_env env, napi_callback_info cbinfo)
753 {
754     HILOGI("called SessionRestore::Release begin");
755     if (!SAUtils::CheckBackupPermission()) {
756         HILOGE("Has not permission!");
757         NError(E_PERMISSION).ThrowErr(env);
758         return nullptr;
759     }
760     if (!SAUtils::IsSystemApp()) {
761         HILOGE("System App check fail!");
762         NError(E_PERMISSION_SYS).ThrowErr(env);
763         return nullptr;
764     }
765     NFuncArg funcArg(env, cbinfo);
766     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
767         HILOGE("Number of arguments unmatched.");
768         NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
769         return nullptr;
770     }
771 
772     auto restoreEntity = NClass::GetEntityOf<RestoreEntity>(env, funcArg.GetThisVar());
773     if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) {
774         HILOGE("Failed to get RestoreSession entity.");
775         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get RestoreSession entity.").GetCode()).ThrowErr(env);
776         return nullptr;
777     }
778 
779     auto cbExec = [entity {restoreEntity}]() -> NError {
780         if (!(entity && (entity->sessionWhole || entity->sessionSheet))) {
781             return NError(BError(BError::Codes::SDK_INVAL_ARG, "restore session is nullptr").GetCode());
782         }
783         if (entity->sessionWhole) {
784             return NError(entity->sessionWhole->Release());
785         }
786         return NError(entity->sessionSheet->Release());
787     };
788     auto cbCompl = [](napi_env env, NError err) -> NVal {
789         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUndefined(env);
790     };
791     HILOGI("Called SessionRestore::Release end.");
792 
793     NVal thisVar(env, funcArg.GetThisVar());
794     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
795 }
796 
Cancel(napi_env env,napi_callback_info info)797 napi_value SessionRestoreNExporter::Cancel(napi_env env, napi_callback_info info)
798 {
799     HILOGD("Called SessionRestore::Cancel begin");
800     if (!SAUtils::CheckBackupPermission()) {
801         HILOGE("Has not permission!");
802         NError(E_PERMISSION).ThrowErr(env);
803         return nullptr;
804     }
805     if (!SAUtils::IsSystemApp()) {
806         HILOGE("System App check fail!");
807         NError(E_PERMISSION_SYS).ThrowErr(env);
808         return nullptr;
809     }
810     NFuncArg funcArg(env, info);
811     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
812         HILOGE("Number of arguments unmatched.");
813         NError(E_PARAMS).ThrowErr(env);
814         return nullptr;
815     }
816     NVal jsBundleStr(env, funcArg[NARG_POS::FIRST]);
817     auto [succStr, bundle, sizeStr] = jsBundleStr.ToUTF8String();
818     if (!succStr) {
819         HILOGE("First argument is not bundleName.");
820         NError(E_PARAMS).ThrowErr(env);
821         return nullptr;
822     }
823     std::string bundleName = bundle.get();
824 
825     auto restoreEntity = NClass::GetEntityOf<RestoreEntity>(env, funcArg.GetThisVar());
826     if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) {
827         HILOGE("Failed to get restoreSession entity.");
828         return nullptr;
829     }
830 
831     int result = BError(BError::Codes::OK);
832     if (restoreEntity->sessionWhole) {
833         result = restoreEntity->sessionWhole->Cancel(bundleName);
834     } else {
835         result = restoreEntity->sessionSheet->Cancel(bundleName);
836     }
837 
838     napi_value nResult;
839     napi_status status = napi_create_int32(env, result, &nResult);
840     if (status != napi_ok) {
841         HILOGE("napi_create_int32 faild.");
842         return nullptr;
843     }
844     HILOGI("Cancel success with result: %{public}d", result);
845     return nResult;
846 }
847 
CleanBundleTempDirCBExec(napi_env env,const NFuncArg & funcArg,std::unique_ptr<char[]> bundleName)848 static NContextCBExec CleanBundleTempDirCBExec(napi_env env, const NFuncArg &funcArg,
849                                                std::unique_ptr<char[]> bundleName)
850 {
851     auto restoreEntity = NClass::GetEntityOf<RestoreEntity>(env, funcArg.GetThisVar());
852     if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) {
853         HILOGE("Failed to get RestoreSession entity.");
854         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get RestoreSession entity.").GetCode()).ThrowErr(env);
855         return nullptr;
856     }
857     return [entity {restoreEntity}, bundleName {string(bundleName.get())}]() -> NError {
858         if (!(entity && (entity->sessionWhole || entity->sessionSheet))) {
859             return NError(BError(BError::Codes::SDK_INVAL_ARG, "restore session is nullptr").GetCode());
860         }
861         if (entity->sessionWhole) {
862             return NError(entity->sessionWhole->CleanBundleTempDir(bundleName));
863         }
864         return NError(entity->sessionSheet->CleanBundleTempDir(bundleName));
865     };
866 }
867 
CleanBundleTempDir(napi_env env,napi_callback_info cbinfo)868 napi_value SessionRestoreNExporter::CleanBundleTempDir(napi_env env, napi_callback_info cbinfo)
869 {
870     HILOGI("Called SessionRestore::CleanBundleTempDir begin.");
871     if (!SAUtils::CheckBackupPermission()) {
872         HILOGE("Has not permission!");
873         NError(E_PERMISSION).ThrowErr(env);
874         return nullptr;
875     }
876     if (!SAUtils::IsSystemApp()) {
877         HILOGE("System App check fail!");
878         NError(E_PERMISSION_SYS).ThrowErr(env);
879         return nullptr;
880     }
881     NFuncArg funcArg(env, cbinfo);
882     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
883         HILOGE("Number of arguments unmatched");
884         NError(E_PARAMS).ThrowErr(env);
885         return nullptr;
886     }
887     NVal jsBundleStr(env, funcArg[NARG_POS::FIRST]);
888     auto [succ, bundleName, sizeStr] = jsBundleStr.ToUTF8String();
889     if (!succ) {
890         HILOGE("First arguments is not string.");
891         NError(E_PARAMS).ThrowErr(env);
892         return nullptr;
893     }
894 
895     auto cbExec = CleanBundleTempDirCBExec(env, funcArg, std::move(bundleName));
896     if (cbExec == nullptr) {
897         HILOGE("CleanBundleTempDirCBExec fail!");
898         return nullptr;
899     }
900     auto cbCompl = [](napi_env env, NError err) -> NVal {
901         return err ? NVal::CreateBool(env, false) : NVal::CreateBool(env, true);
902     };
903 
904     NVal thisVar(env, funcArg.GetThisVar());
905     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
906 }
907 
GetCompatibilityInfoCBExec(napi_env env,const NFuncArg & funcArg,string bundleName,string extInfo,shared_ptr<string> compatInfo)908 static NContextCBExec GetCompatibilityInfoCBExec(napi_env env, const NFuncArg &funcArg, string bundleName,
909     string extInfo, shared_ptr<string> compatInfo)
910 {
911     auto restoreEntity = NClass::GetEntityOf<RestoreEntity>(env, funcArg.GetThisVar());
912     if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) {
913         HILOGE("Failed to get RestoreSession entity.");
914         return nullptr;
915     }
916     return [entity {restoreEntity}, bundleName, extInfo, compatInfo]() -> NError {
917         if (!(entity && (entity->sessionWhole || entity->sessionSheet))) {
918             return NError(BError(BError::Codes::SDK_INVAL_ARG, "restore session is nullptr").GetCode());
919         }
920         if (entity->sessionWhole) {
921             return NError(entity->sessionWhole->GetCompatibilityInfo(bundleName, extInfo, *compatInfo));
922         }
923         return NError(entity->sessionSheet->GetCompatibilityInfo(bundleName, extInfo, *compatInfo));
924     };
925 }
926 
ParseCompatInfoParam(napi_env env,NFuncArg & funcArg,string & bundleName,string & extInfo)927 static bool ParseCompatInfoParam(napi_env env, NFuncArg &funcArg, string &bundleName, string &extInfo)
928 {
929     if (!funcArg.InitArgs(NARG_CNT::TWO)) {
930         HILOGE("Number of arguments unmatched");
931         return false;
932     }
933     NVal jsBundleName(env, funcArg[NARG_POS::FIRST]);
934     auto [succ, bundleNamePtr, sizeStr] = jsBundleName.ToUTF8String();
935     if (!succ) {
936         HILOGE("First arguments is not string.");
937         return false;
938     }
939     NVal jsExtInfo(env, funcArg[NARG_POS::SECOND]);
940     auto [succ1, extInfoPtr, sizeStr1] = jsExtInfo.ToUTF8String();
941     if (!succ1) {
942         HILOGE("Second arguments is not string.");
943         return false;
944     }
945     bundleName = string(bundleNamePtr.get());
946     extInfo = string(extInfoPtr.get());
947     return true;
948 }
949 
GetCompatibilityInfo(napi_env env,napi_callback_info cbinfo)950 napi_value SessionRestoreNExporter::GetCompatibilityInfo(napi_env env, napi_callback_info cbinfo)
951 {
952     HILOGI("Called SessionRestore::GetCompatibilityInfo begin.");
953     if (!SAUtils::CheckBackupPermission()) {
954         HILOGE("Has not permission!");
955         NError(E_PERMISSION).ThrowErr(env);
956         return nullptr;
957     }
958     if (!SAUtils::IsSystemApp()) {
959         HILOGE("System App check fail!");
960         NError(E_PERMISSION_SYS).ThrowErr(env);
961         return nullptr;
962     }
963 
964     NFuncArg funcArg(env, cbinfo);
965     string bundleName;
966     string extInfo;
967     if (!ParseCompatInfoParam(env, funcArg, bundleName, extInfo)) {
968         NError(E_PARAMS).ThrowErr(env);
969         return nullptr;
970     }
971 
972     auto compatInfo = std::make_shared<string>();
973     auto cbExec = GetCompatibilityInfoCBExec(env, funcArg, bundleName, extInfo, compatInfo);
974     if (cbExec == nullptr) {
975         NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get RestoreSession entity.").GetCode()).ThrowErr(env);
976         return nullptr;
977     }
978     auto cbCompl = [compatInfo](napi_env env, NError err) -> NVal {
979         return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUTF8String(env, *compatInfo);
980     };
981 
982     NVal thisVar(env, funcArg.GetThisVar());
983     return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_;
984 }
985 
Export()986 bool SessionRestoreNExporter::Export()
987 {
988     HILOGD("called SessionRestoreNExporter::Export begin");
989     vector<napi_property_descriptor> props = {
990         NVal::DeclareNapiFunction("getLocalCapabilities", GetLocalCapabilities),
991         NVal::DeclareNapiFunction("appendBundles", AppendBundles),
992         NVal::DeclareNapiFunction("publishFile", PublishFile),
993         NVal::DeclareNapiFunction("getFileHandle", GetFileHandle),
994         NVal::DeclareNapiFunction("release", Release),
995         NVal::DeclareNapiFunction("cancel", Cancel),
996         NVal::DeclareNapiFunction("cleanBundleTempDir", CleanBundleTempDir),
997         NVal::DeclareNapiFunction("getCompatibilityInfo", GetCompatibilityInfo),
998     };
999 
1000     auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props));
1001     if (!succ) {
1002         HILOGE("Failed to define class");
1003         NError(EIO).ThrowErr(exports_.env_);
1004         return false;
1005     }
1006     succ = NClass::SaveClass(exports_.env_, className, classValue);
1007     if (!succ) {
1008         HILOGE("Failed to save class");
1009         NError(EIO).ThrowErr(exports_.env_);
1010         return false;
1011     }
1012 
1013     HILOGD("called SessionRestoreNExporter::Export end");
1014     return exports_.AddProp(className, classValue);
1015 }
1016 
GetClassName()1017 string SessionRestoreNExporter::GetClassName()
1018 {
1019     return SessionRestoreNExporter::className;
1020 }
1021 
SessionRestoreNExporter(napi_env env,napi_value exports)1022 SessionRestoreNExporter::SessionRestoreNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
1023 
~SessionRestoreNExporter()1024 SessionRestoreNExporter::~SessionRestoreNExporter() {}
1025 } // namespace OHOS::FileManagement::Backup