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