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