• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 
16 #include "ext_backup_js.h"
17 
18 #include <cstdio>
19 #include <memory>
20 #include <sstream>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 
24 #include "bundle_mgr_client.h"
25 #include "ext_backup_context_js.h"
26 #include "js_extension_context.h"
27 #include "js_native_api.h"
28 #include "js_native_api_types.h"
29 #include "js_runtime.h"
30 #include "js_runtime_utils.h"
31 #include "napi/native_api.h"
32 #include "napi/native_node_api.h"
33 #include "napi_common_util.h"
34 #include "napi_common_want.h"
35 #include "napi_remote_object.h"
36 #include "unique_fd.h"
37 
38 #include "b_anony/b_anony.h"
39 #include "b_error/b_error.h"
40 #include "b_error/b_excep_utils.h"
41 #include "b_json/b_json_cached_entity.h"
42 #include "b_json/b_json_entity_extension_config.h"
43 #include "b_radar/b_radar.h"
44 #include "b_resources/b_constants.h"
45 #include "directory_ex.h"
46 #include "ext_extension.h"
47 #include "filemgmt_libhilog.h"
48 
49 namespace OHOS::FileManagement::Backup {
50 using namespace std;
51 constexpr size_t ARGC_ONE = 1;
52 static std::mutex g_extBackupValidLock;
53 static int32_t g_extBackupCount = 0;
54 
GetSrcPath(const AppExecFwk::AbilityInfo & info)55 static string GetSrcPath(const AppExecFwk::AbilityInfo &info)
56 {
57     using AbilityRuntime::Extension;
58     stringstream ss;
59 
60     // API9(stage model) 中通过 $(module)$(name)/$(srcEntrance/(.*$)/(.abc)) 获取自定义插件路径
61     if (!info.srcEntrance.empty()) {
62         ss << info.moduleName << '/' << string(info.srcEntrance, 0, info.srcEntrance.rfind(".")) << ".abc";
63         return ss.str();
64     }
65     return "";
66 }
67 
DealNapiStrValue(napi_env env,const napi_value napi_StrValue,std::string & result)68 static napi_status DealNapiStrValue(napi_env env, const napi_value napi_StrValue, std::string &result)
69 {
70     HILOGI("Start DealNapiStrValue");
71     std::string buffer = "";
72     size_t bufferSize = 0;
73     napi_status status = napi_ok;
74     status = napi_get_value_string_utf8(env, napi_StrValue, nullptr, -1, &bufferSize);
75     if (status != napi_ok) {
76         HILOGE("Can not get buffer size");
77         return status;
78     }
79     buffer.reserve(bufferSize + 1);
80     buffer.resize(bufferSize);
81     if (bufferSize > 0) {
82         status = napi_get_value_string_utf8(env, napi_StrValue, buffer.data(), bufferSize + 1, &bufferSize);
83         if (status != napi_ok) {
84             HILOGE("Can not get buffer value");
85             return status;
86         }
87     }
88     result = buffer;
89     return status;
90 }
91 
DealNapiException(napi_env env,napi_value & exception,std::string & exceptionInfo)92 static napi_status DealNapiException(napi_env env, napi_value &exception, std::string &exceptionInfo)
93 {
94     HILOGI("call DealNapiException start.");
95     napi_status status = napi_get_and_clear_last_exception(env, &exception);
96     if (status != napi_ok) {
97         HILOGE("call napi_get_and_clear_last_exception failed.");
98         return status;
99     }
100     status = DealNapiStrValue(env, exception, exceptionInfo);
101     if (status != napi_ok) {
102         HILOGE("call DealNapiStrValue failed.");
103         return status;
104     }
105     HILOGI("call DealNapiException end, exception info = %{public}s.", exceptionInfo.c_str());
106     return status;
107 }
108 
PromiseCallback(napi_env env,napi_callback_info info)109 static napi_value PromiseCallback(napi_env env, napi_callback_info info)
110 {
111     std::lock_guard<std::mutex> lock(g_extBackupValidLock);
112     if (g_extBackupCount <= 0) {
113         HILOGE("ExtBackup is invalid, count=%{public}d", g_extBackupCount);
114         return nullptr;
115     }
116     HILOGI("Promise callback.");
117     void *data = nullptr;
118     if (napi_get_cb_info(env, info, nullptr, 0, nullptr, &data) != napi_ok) {
119         HILOGE("Failed to get callback info.");
120         return nullptr;
121     }
122     auto *callbackInfo = static_cast<CallbackInfo *>(data);
123     if (callbackInfo == nullptr) {
124         HILOGE("CallbackInfo is nullptr");
125         return nullptr;
126     }
127     string str;
128     callbackInfo->callback(BError(BError::Codes::OK), str);
129     data = nullptr;
130     return nullptr;
131 }
132 
PromiseCatchCallback(napi_env env,napi_callback_info info)133 static napi_value PromiseCatchCallback(napi_env env, napi_callback_info info)
134 {
135     HILOGI("Promise catch callback begin.");
136     size_t argc = 1;
137     napi_value argv = {nullptr};
138     void *data = nullptr;
139     NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, &argc, &argv, nullptr, &data), nullptr);
140     string exceptionInfo;
141     DealNapiStrValue(env, argv, exceptionInfo);
142     HILOGI("Catch exception info is %{public}s.", exceptionInfo.c_str());
143     auto *callbackInfo = static_cast<CallbackInfo *>(data);
144     if (callbackInfo == nullptr) {
145         HILOGE("CallbackInfo is nullptr");
146         return nullptr;
147     }
148     napi_status throwStatus = napi_fatal_exception(env, argv);
149     if (throwStatus != napi_ok) {
150         HILOGE("Failed to throw an exception, %{public}d", throwStatus);
151         return nullptr;
152     }
153     std::lock_guard<std::mutex> lock(g_extBackupValidLock);
154     if (g_extBackupCount <= 0) {
155         HILOGE("ExtBackup is invalid, count=%{public}d", g_extBackupCount);
156         data = nullptr;
157         return nullptr;
158     }
159     callbackInfo->callback(BError(BError::Codes::EXT_THROW_EXCEPTION), exceptionInfo);
160     data = nullptr;
161     HILOGI("Promise catch callback end.");
162     return nullptr;
163 }
164 
PromiseCallbackEx(napi_env env,napi_callback_info info)165 static napi_value PromiseCallbackEx(napi_env env, napi_callback_info info)
166 {
167     std::lock_guard<std::mutex> lock(g_extBackupValidLock);
168     if (g_extBackupCount <= 0) {
169         HILOGE("ExtBackup is invalid, count=%{public}d", g_extBackupCount);
170         return nullptr;
171     }
172     HILOGI("PromiseEx callback.");
173     void *data = nullptr;
174     std::string str;
175     size_t argc = 1;
176     napi_value argv = {nullptr};
177     NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, &argc, &argv, nullptr, &data), nullptr);
178     auto *callbackInfoEx = static_cast<CallbackInfoEx *>(data);
179     if (callbackInfoEx == nullptr) {
180         HILOGE("CallbackInfo is nullPtr");
181         return nullptr;
182     }
183     DealNapiStrValue(env, argv, str);
184     callbackInfoEx->callbackParam(BError(BError::Codes::OK), str);
185     data = nullptr;
186     return nullptr;
187 }
188 
PromiseCatchCallbackEx(napi_env env,napi_callback_info info)189 static napi_value PromiseCatchCallbackEx(napi_env env, napi_callback_info info)
190 {
191     HILOGI("PromiseEx catch callback begin.");
192     void *data = nullptr;
193     size_t argc = 1;
194     napi_value argv = {nullptr};
195     NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, &argc, &argv, nullptr, &data), nullptr);
196     string exceptionInfo;
197     DealNapiStrValue(env, argv, exceptionInfo);
198     HILOGI("Catch exception info is %{public}s.", exceptionInfo.c_str());
199     auto *callbackInfoEx = static_cast<CallbackInfoEx *>(data);
200     if (callbackInfoEx == nullptr) {
201         HILOGE("CallbackInfo is nullPtr");
202         return nullptr;
203     }
204     napi_status throwStatus = napi_fatal_exception(env, argv);
205     if (throwStatus != napi_ok) {
206         HILOGE("Failed to throw an exception, %{public}d", throwStatus);
207         return nullptr;
208     }
209     std::lock_guard<std::mutex> lock(g_extBackupValidLock);
210     if (g_extBackupCount <= 0) {
211         HILOGE("ExtBackup is invalid, count=%{public}d", g_extBackupCount);
212         data = nullptr;
213         return nullptr;
214     }
215     callbackInfoEx->callbackParam(BError(BError::Codes::EXT_THROW_EXCEPTION), exceptionInfo);
216     data = nullptr;
217     HILOGI("PromiseEx catch callback end.");
218     return nullptr;
219 }
220 
CheckPromise(napi_env env,napi_value value)221 static bool CheckPromise(napi_env env, napi_value value)
222 {
223     if (value == nullptr) {
224         HILOGE("CheckPromise, result is null, no need to call promise.");
225         return false;
226     }
227     bool isPromise = false;
228     if (napi_is_promise(env, value, &isPromise) != napi_ok) {
229         HILOGE("CheckPromise, result is not promise, no need to call promise.");
230         return false;
231     }
232     return isPromise;
233 }
234 
CallCatchPromise(AbilityRuntime::JsRuntime & jsRuntime,napi_value result,CallbackInfo * callbackInfo)235 static bool CallCatchPromise(AbilityRuntime::JsRuntime &jsRuntime, napi_value result, CallbackInfo *callbackInfo)
236 {
237     HILOGI("CallCatchPromise Begin.");
238     AbilityRuntime::HandleScope handleScope(jsRuntime);
239     auto env = jsRuntime.GetNapiEnv();
240     napi_value method = nullptr;
241     if (napi_get_named_property(env, result, "catch", &method) != napi_ok) {
242         HILOGE("CallCatchPromise, Failed to get method catch");
243         return false;
244     }
245     bool isCallable = false;
246     if (napi_is_callable(env, method, &isCallable) != napi_ok) {
247         HILOGE("CallCatchPromise, Failed to check method then is callable");
248         return false;
249     }
250     if (!isCallable) {
251         HILOGE("CallCatchPromise, property then is not callable.");
252         return false;
253     }
254     napi_value ret;
255     if (napi_create_function(env, "promiseCatchCallback", strlen("promiseCatchCallback"), PromiseCatchCallback,
256         callbackInfo, &ret) != napi_ok) {
257         HILOGE("napi create function failed");
258         return false;
259     }
260     napi_value argv[1] = {ret};
261     if (napi_call_function(env, result, method, 1, argv, nullptr) != napi_ok) {
262         HILOGE("napi call function failed");
263         return false;
264     }
265     return true;
266 }
267 
CallPromise(AbilityRuntime::JsRuntime & jsRuntime,napi_value result,CallbackInfo * callbackInfo)268 static bool CallPromise(AbilityRuntime::JsRuntime &jsRuntime, napi_value result, CallbackInfo *callbackInfo)
269 {
270     AbilityRuntime::HandleScope handleScope(jsRuntime);
271     auto env = jsRuntime.GetNapiEnv();
272     napi_value method = nullptr;
273     if (napi_get_named_property(env, result, "then", &method) != napi_ok) {
274         HILOGE("CallPromise, Failed to get method then");
275         return false;
276     }
277     bool isCallable = false;
278     if (napi_is_callable(env, method, &isCallable) != napi_ok) {
279         HILOGE("CallPromise, Failed to check method then is callable");
280         return false;
281     }
282     if (!isCallable) {
283         HILOGE("CallPromise, property then is not callable.");
284         return false;
285     }
286     napi_value ret;
287     if (napi_create_function(env, "promiseCallback", strlen("promiseCallback"), PromiseCallback, callbackInfo, &ret) !=
288         napi_ok) {
289         HILOGE("napi create function failed");
290         return false;
291     }
292     napi_value argv[1] = {ret};
293     if (napi_call_function(env, result, method, 1, argv, nullptr) != napi_ok) {
294         HILOGE("napi call function failed");
295         return false;
296     }
297     if (!CallCatchPromise(jsRuntime, result, callbackInfo)) {
298         HILOGE("CallCatchPromise failed.");
299         return false;
300     }
301     return true;
302 }
303 
CallCatchPromiseEx(AbilityRuntime::JsRuntime & jsRuntime,napi_value result,CallbackInfoEx * callbackInfoEx)304 static bool CallCatchPromiseEx(AbilityRuntime::JsRuntime &jsRuntime, napi_value result, CallbackInfoEx *callbackInfoEx)
305 {
306     HILOGI("CallCatchPromiseEx Begin.");
307     AbilityRuntime::HandleScope handleScope(jsRuntime);
308     auto env = jsRuntime.GetNapiEnv();
309     napi_value method = nullptr;
310     if (napi_get_named_property(env, result, "catch", &method) != napi_ok) {
311         HILOGE("CallCatchPromiseEx, Failed to get method catch");
312         return false;
313     }
314     bool isCallable = false;
315     if (napi_is_callable(env, method, &isCallable) != napi_ok) {
316         HILOGE("CallCatchPromiseEx, Failed to check method then is callable");
317         return false;
318     }
319     if (!isCallable) {
320         HILOGE("CallCatchPromiseEx, property then is not callable.");
321         return false;
322     }
323     napi_value ret;
324     if (napi_create_function(env, "promiseCatchCallbackEx", strlen("promiseCatchCallbackEx"), PromiseCatchCallbackEx,
325         callbackInfoEx, &ret) != napi_ok) {
326         HILOGE("napi create function failed");
327         return false;
328     }
329     napi_value argv[1] = {ret};
330     if (napi_call_function(env, result, method, 1, argv, nullptr) != napi_ok) {
331         HILOGE("napi call function failed");
332         return false;
333     }
334     return true;
335 }
336 
CallPromiseEx(AbilityRuntime::JsRuntime & jsRuntime,napi_value result,CallbackInfoEx * callbackInfoEx)337 static bool CallPromiseEx(AbilityRuntime::JsRuntime &jsRuntime, napi_value result, CallbackInfoEx *callbackInfoEx)
338 {
339     AbilityRuntime::HandleScope handleScope(jsRuntime);
340     auto env = jsRuntime.GetNapiEnv();
341     napi_value method = nullptr;
342     if (napi_get_named_property(env, result, "then", &method) != napi_ok) {
343         HILOGE("CallPromise, Failed to get method then");
344         return false;
345     }
346     bool isCallable = false;
347     if (napi_is_callable(env, method, &isCallable) != napi_ok) {
348         HILOGE("CallPromise, Failed to check method then is callable");
349         return false;
350     }
351     if (!isCallable) {
352         HILOGE("CallPromise, property then is not callable.");
353         return false;
354     }
355     napi_value ret;
356     if (napi_create_function(env, "promiseCallbackEx", strlen("promiseCallbackEx"), PromiseCallbackEx, callbackInfoEx,
357         &ret) != napi_ok) {
358         HILOGE("napi create function failed");
359         return false;
360     }
361     napi_value argv[1] = {ret};
362     if (napi_call_function(env, result, method, 1, argv, nullptr) != napi_ok) {
363         HILOGE("napi call function failed");
364         return false;
365     }
366     if (!CallCatchPromiseEx(jsRuntime, result, callbackInfoEx)) {
367         HILOGE("CallCatchPromiseEx failed.");
368         return false;
369     }
370     return true;
371 }
372 
CallPromiseEx(AbilityRuntime::JsRuntime & jsRuntime,napi_value result,CallbackInfoBackup * callbackInfoBackup)373 static bool CallPromiseEx(AbilityRuntime::JsRuntime &jsRuntime, napi_value result,
374     CallbackInfoBackup *callbackInfoBackup)
375 {
376     AbilityRuntime::HandleScope handleScope(jsRuntime);
377     auto env = jsRuntime.GetNapiEnv();
378     napi_value method = nullptr;
379     if (napi_get_named_property(env, result, "then", &method) != napi_ok) {
380         HILOGE("CallPromise, Failed to get method then");
381         return false;
382     }
383     bool isCallable = false;
384     if (napi_is_callable(env, method, &isCallable) != napi_ok) {
385         HILOGE("CallPromise, Failed to check method then is callable");
386         return false;
387     }
388     if (!isCallable) {
389         HILOGE("CallPromise, property then is not callable.");
390         return false;
391     }
392     napi_value ret;
393     if (napi_create_function(env, "promiseCallbackEx", strlen("promiseCallbackEx"), PromiseCallbackEx,
394         callbackInfoBackup, &ret) != napi_ok) {
395         HILOGE("napi create function failed");
396         return false;
397     }
398     napi_value argv[1] = {ret};
399     if (napi_call_function(env, result, method, 1, argv, nullptr) != napi_ok) {
400         HILOGE("napi call function failed");
401         return false;
402     }
403     return true;
404 }
405 
Init(const shared_ptr<AppExecFwk::AbilityLocalRecord> & record,const shared_ptr<AppExecFwk::OHOSApplication> & application,shared_ptr<AppExecFwk::AbilityHandler> & handler,const sptr<IRemoteObject> & token)406 void ExtBackupJs::Init(const shared_ptr<AppExecFwk::AbilityLocalRecord> &record,
407                        const shared_ptr<AppExecFwk::OHOSApplication> &application,
408                        shared_ptr<AppExecFwk::AbilityHandler> &handler,
409                        const sptr<IRemoteObject> &token)
410 {
411     HILOGI("Init the BackupExtensionAbility(JS)");
412     try {
413         ExtBackup::Init(record, application, handler, token);
414         BExcepUltils::BAssert(abilityInfo_, BError::Codes::EXT_BROKEN_FRAMEWORK, "Invalid abilityInfo_");
415         // 获取应用扩展的 BackupExtensionAbility 的路径
416         const AppExecFwk::AbilityInfo &info = *abilityInfo_;
417         string bundleName = info.bundleName;
418         InitTempPath(bundleName);
419         string moduleName(info.moduleName + "::" + info.name);
420         string modulePath = GetSrcPath(info);
421         int moduleType = static_cast<int>(info.type);
422         HILOGI("Try to load %{public}s's %{public}s(type %{public}d) from %{public}s", bundleName.c_str(),
423                moduleName.c_str(), moduleType, modulePath.c_str());
424 
425         // 加载用户扩展 BackupExtensionAbility 到 JS 引擎,并将之暂存在 jsObj_ 中。注意,允许加载失败,往后执行默认逻辑
426         AbilityRuntime::HandleScope handleScope(jsRuntime_);
427         jsObj_ = jsRuntime_.LoadModule(moduleName, modulePath, info.hapPath,
428                                        abilityInfo_->compileMode == AbilityRuntime::CompileMode::ES_MODULE);
429         if (jsObj_ == nullptr) {
430             HILOGW("Oops! There's no custom BackupExtensionAbility");
431             return;
432         }
433         HILOGI("Wow! Here's a custsom BackupExtensionAbility");
434         ExportJsContext();
435     } catch (const BError &e) {
436         HILOGE("%{public}s", e.what());
437     } catch (const exception &e) {
438         HILOGE("%{public}s", e.what());
439     }
440 }
441 
AttachBackupExtensionContext(napi_env env,void * value,void *)442 napi_value AttachBackupExtensionContext(napi_env env, void *value, void *)
443 {
444     HILOGI("AttachBackupExtensionContext");
445     if (value == nullptr || env == nullptr) {
446         HILOG_WARN("invalid parameter.");
447         return nullptr;
448     }
449     auto ptr = reinterpret_cast<std::weak_ptr<ExtBackupContext> *>(value)->lock();
450     if (ptr == nullptr) {
451         HILOGE("invalid context.");
452         return nullptr;
453     }
454     auto object = CreateExtBackupJsContext(env, ptr);
455     if (object == nullptr) {
456         HILOGE("Failed to get js backup extension context");
457         return nullptr;
458     }
459     auto contextRef =
460         AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(env, "application.BackupExtensionContext", &object, 1);
461     if (contextRef == nullptr) {
462         HILOGE("Failed to load BackupExtensionContext.");
463         return nullptr;
464     }
465     napi_value contextObj = contextRef->GetNapiValue();
466     napi_coerce_to_native_binding_object(env, contextObj, AbilityRuntime::DetachCallbackFunc,
467                                          AttachBackupExtensionContext, value, nullptr);
468 
469     auto workContext = new (std::nothrow) std::weak_ptr<ExtBackupContext>(ptr);
470     if (workContext == nullptr) {
471         HILOGE("Failed to get backup extension context");
472         return nullptr;
473     }
474     napi_status status = napi_wrap(
475         env, contextObj, workContext,
476         [](napi_env, void *data, void *) {
477             HILOG_DEBUG("Finalizer for weak_ptr base context is called");
478             delete static_cast<std::weak_ptr<ExtBackupContext> *>(data);
479         },
480         nullptr, nullptr);
481     if (status != napi_ok) {
482         HILOG_DEBUG("Failed to wrap js instance");
483         delete workContext;
484         workContext = nullptr;
485     }
486     return contextObj;
487 }
488 
ExtBackupJs(AbilityRuntime::JsRuntime & jsRuntime)489 ExtBackupJs::ExtBackupJs(AbilityRuntime::JsRuntime &jsRuntime) : jsRuntime_(jsRuntime)
490 {
491     std::lock_guard<std::mutex> lock(g_extBackupValidLock);
492     g_extBackupCount += 1;
493     HILOGI("ExtBackupJs::ExtBackupJs, count=%{public}d.", g_extBackupCount);
494 }
495 
~ExtBackupJs()496 ExtBackupJs::~ExtBackupJs()
497 {
498     jsRuntime_.FreeNativeReference(std::move(jsObj_));
499     std::lock_guard<std::mutex> lock(g_extBackupValidLock);
500     g_extBackupCount -= 1;
501     HILOGI("ExtBackupJs::~ExtBackupJs, count=%{public}d.", g_extBackupCount);
502 }
503 
ExportJsContext(void)504 void ExtBackupJs::ExportJsContext(void)
505 {
506     auto env = jsRuntime_.GetNapiEnv();
507     if (jsObj_ == nullptr) {
508         HILOGE("Failed to get js object.");
509         return;
510     }
511     napi_value obj = jsObj_->GetNapiValue();
512     if (obj == nullptr) {
513         HILOGE("Failed to get BackupExtAbility object");
514         return;
515     }
516 
517     auto context = GetContext();
518     if (context == nullptr) {
519         HILOGE("Failed to get context");
520         return;
521     }
522 
523     HILOGI("CreateBackupExtAbilityContext");
524     napi_value contextObj = CreateExtBackupJsContext(env, context);
525     auto contextRef = jsRuntime_.LoadSystemModule("application.BackupExtensionContext", &contextObj, ARGC_ONE);
526     if (!contextRef) {
527         HILOGE("context is nullptr");
528         return;
529     }
530     contextObj = contextRef->GetNapiValue();
531     HILOGI("Bind context");
532     context->Bind(jsRuntime_, contextRef.release());
533     napi_set_named_property(env, obj, "context", contextObj);
534 
535     auto workContext = new (std::nothrow) std::weak_ptr<ExtBackupContext>(context);
536     if (workContext == nullptr) {
537         HILOGE("Failed to create ExtBackupContext.");
538         return;
539     }
540     napi_coerce_to_native_binding_object(env, contextObj, AbilityRuntime::DetachCallbackFunc,
541                                          AttachBackupExtensionContext, workContext, nullptr);
542     HILOGI("Set backup extension ability context pointer is nullptr: %{public}d", context.get() == nullptr);
543     napi_status status = napi_wrap(
544         env, contextObj, workContext,
545         [](napi_env, void *data, void *) {
546             HILOG_DEBUG("Finalizer for weak_ptr base context is called");
547             delete static_cast<std::weak_ptr<ExtBackupContext> *>(data);
548         },
549         nullptr, nullptr);
550     if (status != napi_ok) {
551         HILOG_DEBUG("Failed to wrap js instance");
552         delete workContext;
553         workContext = nullptr;
554     }
555 }
556 
CallObjectMethod(string_view name,const vector<napi_value> & argv)557 [[maybe_unused]] tuple<ErrCode, napi_value> ExtBackupJs::CallObjectMethod(string_view name,
558                                                                           const vector<napi_value> &argv)
559 {
560     HILOGI("Call %{public}s", name.data());
561     return {BError(BError::Codes::OK).GetCode(), nullptr};
562 }
563 
Create(const unique_ptr<AbilityRuntime::Runtime> & runtime)564 ExtBackupJs *ExtBackupJs::Create(const unique_ptr<AbilityRuntime::Runtime> &runtime)
565 {
566     HILOGI("Create as an BackupExtensionAbility(JS)");
567     return new ExtBackupJs(static_cast<AbilityRuntime::JsRuntime &>(*runtime));
568 }
569 
OnBackup(function<void (ErrCode,std::string)> callback,std::function<void (ErrCode,const std::string)> callbackEx)570 ErrCode ExtBackupJs::OnBackup(function<void(ErrCode, std::string)> callback,
571     std::function<void(ErrCode, const std::string)> callbackEx)
572 {
573     HILOGI("BackupExtensionAbility(JS) OnBackup ex");
574     BExcepUltils::BAssert(jsObj_, BError::Codes::EXT_BROKEN_FRAMEWORK,
575         "The app does not provide the onBackup interface.");
576     BExcepUltils::BAssert(callback, BError::Codes::EXT_BROKEN_FRAMEWORK, "OnBackup callback is nullptr.");
577     BExcepUltils::BAssert(callbackEx, BError::Codes::EXT_BROKEN_FRAMEWORK, "OnBackup callbackEx is nullptr.");
578     callExtDefaultFunc_.store(false);
579     callJsExMethodDone_.store(false);
580     callbackInfo_ = std::make_shared<CallbackInfo>(callback);
581     callbackInfoEx_ = std::make_shared<CallbackInfoEx>(callbackEx);
582     return CallJsOnBackupEx();
583 }
584 
CallJsOnBackupEx()585 ErrCode ExtBackupJs::CallJsOnBackupEx()
586 {
587     HILOGI("Start call app js method onBackupEx");
588     auto retParser = [jsRuntime{ &jsRuntime_ }, callbackInfoEx { callbackInfoEx_ }](napi_env envir,
589         napi_value result) -> bool {
590         if (!CheckPromise(envir, result)) {
591             string str;
592             bool isExceptionPending;
593             napi_is_exception_pending(envir, &isExceptionPending);
594             HILOGI("napi exception pending = %{public}d.", isExceptionPending);
595             if (!callbackInfoEx) {
596                 HILOGE("callbackInfoEx is nullptr");
597                 return false;
598             }
599             if (isExceptionPending) {
600                 napi_value exception;
601                 DealNapiException(envir, exception, str);
602                 napi_fatal_exception(envir, exception);
603                 callbackInfoEx->callbackParam(BError(BError::Codes::EXT_THROW_EXCEPTION), str);
604             } else {
605                 DealNapiStrValue(envir, result, str);
606                 callbackInfoEx->callbackParam(BError(BError::Codes::OK), str);
607             }
608             return true;
609         }
610         HILOGI("CheckPromise onBackupEx ok");
611         return CallPromiseEx(*jsRuntime, result, callbackInfoEx.get());
612     };
613     auto errCode = CallJsMethod("onBackupEx", jsRuntime_, jsObj_.get(), ParseBackupExInfo(), retParser);
614     if (errCode != ERR_OK) {
615         HILOGE("Call onBackupEx error");
616         return errCode;
617     }
618     HILOGI("Check call onBackupEx load");
619     std::unique_lock<std::mutex> lock(callJsMutex_);
620     callJsCon_.wait(lock, [this] { return callJsExMethodDone_.load(); });
621 
622     if (!callExtDefaultFunc_.load()) {
623         HILOGI("Call Js method onBackupEx done");
624         return ERR_OK;
625     }
626     return CallJsOnBackup();
627 }
628 
CallJsOnBackup()629 ErrCode ExtBackupJs::CallJsOnBackup()
630 {
631     HILOGI("Start call app js method onBackup");
632     auto retParser = [jsRuntime {&jsRuntime_}, callbackInfo {callbackInfo_}](napi_env env,
633         napi_value result) -> bool {
634         if (!CheckPromise(env, result)) {
635             string str;
636             bool isExceptionPending;
637             napi_is_exception_pending(env, &isExceptionPending);
638             HILOGI("napi exception pending = %{public}d.", isExceptionPending);
639             if (!callbackInfo) {
640                 HILOGE("callbackInfo is nullptr");
641                 return false;
642             }
643             if (isExceptionPending) {
644                 napi_value exception;
645                 DealNapiException(env, exception, str);
646                 napi_fatal_exception(env, exception);
647                 callbackInfo->callback(BError(BError::Codes::EXT_THROW_EXCEPTION), str);
648             } else {
649                 callbackInfo->callback(BError(BError::Codes::OK), str);
650             }
651             return true;
652         }
653         HILOGI("CheckPromise Js Method onBackup ok.");
654         return CallPromise(*jsRuntime, result, callbackInfo.get());
655     };
656     auto errCode = CallJsMethod("onBackup", jsRuntime_, jsObj_.get(), {}, retParser);
657     if (errCode != ERR_OK) {
658         HILOGE("CallJsMethod error, code:%{public}d.", errCode);
659     }
660     return errCode;
661 }
662 
OnRestore(function<void (ErrCode,std::string)> callback,std::function<void (ErrCode,const std::string)> callbackEx)663 ErrCode ExtBackupJs::OnRestore(function<void(ErrCode, std::string)> callback,
664     std::function<void(ErrCode, const std::string)> callbackEx)
665 {
666     HILOGI("BackupExtensionAbility(JS) OnRestore.");
667     BExcepUltils::BAssert(jsObj_, BError::Codes::EXT_BROKEN_FRAMEWORK,
668         "The app does not provide the onRestore interface.");
669     BExcepUltils::BAssert(callback, BError::Codes::EXT_BROKEN_FRAMEWORK, "OnRestore callback is nullptr.");
670     BExcepUltils::BAssert(callbackEx, BError::Codes::EXT_BROKEN_FRAMEWORK, "OnRestore callbackEx is nullptr.");
671     callExtDefaultFunc_.store(false);
672     callJsExMethodDone_.store(false);
673     callbackInfo_ = std::make_shared<CallbackInfo>(callback);
674     callbackInfoEx_ = std::make_shared<CallbackInfoEx>(callbackEx);
675     return CallJSRestoreEx();
676 }
677 
CallJSRestoreEx()678 ErrCode ExtBackupJs::CallJSRestoreEx()
679 {
680     HILOGI("Start call app js method onRestoreEx");
681     auto retParser = [jsRuntime {&jsRuntime_}, callbackInfoEx {callbackInfoEx_}](napi_env envir, napi_value result) ->
682         bool {
683         if (!CheckPromise(envir, result)) {
684             string str;
685             bool isExceptionPending;
686             napi_is_exception_pending(envir, &isExceptionPending);
687             HILOGI("napi exception pending = %{public}d.", isExceptionPending);
688             if (!callbackInfoEx) {
689                 HILOGE("callbackInfoEx is nullptr");
690                 return false;
691             }
692             if (isExceptionPending) {
693                 napi_value exception;
694                 DealNapiException(envir, exception, str);
695                 napi_fatal_exception(envir, exception);
696                 callbackInfoEx->callbackParam(BError(BError::Codes::EXT_THROW_EXCEPTION), str);
697             } else {
698                 DealNapiStrValue(envir, result, str);
699                 callbackInfoEx->callbackParam(BError(BError::Codes::OK), str);
700             }
701             return true;
702         }
703         HILOGI("CheckPromise onRestoreEx ok");
704         return CallPromiseEx(*jsRuntime, result, callbackInfoEx.get());
705     };
706     auto errCode = CallJsMethod("onRestoreEx", jsRuntime_, jsObj_.get(), ParseRestoreExInfo(), retParser);
707     if (errCode != ERR_OK) {
708         HILOGE("Call onRestoreEx error");
709         return errCode;
710     }
711     HILOGI("Check callRestoreExDone load");
712     std::unique_lock<std::mutex> lock(callJsMutex_);
713     callJsCon_.wait(lock, [this] { return callJsExMethodDone_.load(); });
714     HILOGI("Check needCallOnRestore load");
715     if (!callExtDefaultFunc_.load()) {
716         HILOGI("Call Js method onRestoreEx done");
717         return ERR_OK;
718     }
719     return CallJSRestore();
720 }
721 
CallJSRestore()722 ErrCode ExtBackupJs::CallJSRestore()
723 {
724     HILOGI("Start call app js method onRestore");
725     auto retParser = [jsRuntime {&jsRuntime_}, callbackInfo {callbackInfo_}](napi_env env, napi_value result) -> bool {
726         if (!CheckPromise(env, result)) {
727             string str;
728             bool isExceptionPending;
729             napi_is_exception_pending(env, &isExceptionPending);
730             HILOGI("napi exception pending = %{public}d.", isExceptionPending);
731             if (!callbackInfo) {
732                 HILOGE("callbackInfo is nullptr");
733                 return false;
734             }
735             if (isExceptionPending) {
736                 napi_value exception;
737                 DealNapiException(env, exception, str);
738                 napi_fatal_exception(env, exception);
739                 callbackInfo->callback(BError(BError::Codes::EXT_THROW_EXCEPTION), str);
740             } else {
741                 callbackInfo->callback(BError(BError::Codes::OK), str);
742             }
743             return true;
744         }
745         HILOGI("CheckPromise Js Method onRestore ok.");
746         return CallPromise(*jsRuntime, result, callbackInfo.get());
747     };
748     auto errCode = CallJsMethod("onRestore", jsRuntime_, jsObj_.get(), ParseRestoreInfo(), retParser);
749     if (errCode != ERR_OK) {
750         HILOGE("CallJsMethod error, code:%{public}d.", errCode);
751         return errCode;
752     }
753     return ERR_OK;
754 }
755 
GetBackupInfo(std::function<void (ErrCode,const std::string)> callback)756 ErrCode ExtBackupJs::GetBackupInfo(std::function<void(ErrCode, const std::string)> callback)
757 {
758     HILOGI("BackupExtensionAbility(JS) GetBackupInfo begin.");
759     BExcepUltils::BAssert(jsObj_, BError::Codes::EXT_BROKEN_FRAMEWORK,
760                           "The app does not provide the GetBackupInfo interface.");
761     callbackInfoBackup_ = std::make_shared<CallbackInfoBackup>(callback);
762     auto retParser = [jsRuntime {&jsRuntime_}, callBackInfo {callbackInfoBackup_}](napi_env env,
763         napi_value result) -> bool {
764         if (!CheckPromise(env, result)) {
765             bool isExceptionPending;
766             napi_is_exception_pending(env, &isExceptionPending);
767             HILOGI("napi exception pending = %{public}d.", isExceptionPending);
768             if (!callBackInfo) {
769                 HILOGE("callBackInfo is nullptr");
770                 return false;
771             }
772             if (isExceptionPending) {
773                 string str;
774                 napi_value exception;
775                 DealNapiException(env, exception, str);
776                 callBackInfo->callbackParam(BError(BError::Codes::EXT_THROW_EXCEPTION), str);
777                 return false;
778             }
779             size_t strLen = 0;
780             napi_status status = napi_get_value_string_utf8(env, result, nullptr, -1, &strLen);
781             if (status != napi_ok) {
782                 return false;
783             }
784             size_t bufLen = strLen + 1;
785             unique_ptr<char[]> str = make_unique<char[]>(bufLen);
786             status = napi_get_value_string_utf8(env, result, str.get(), bufLen, &strLen);
787             callBackInfo->callbackParam(BError(BError::Codes::OK), str.get());
788             return true;
789         }
790         HILOGI("BackupExtensionAbulity(JS) GetBackupInfo ok.");
791         return CallPromiseEx(*jsRuntime, result, callBackInfo.get());
792     };
793 
794     auto errCode = CallJsMethod("getBackupInfo", jsRuntime_, jsObj_.get(), {}, retParser);
795     if (errCode != ERR_OK) {
796         HILOGE("CallJsMethod error, code:%{public}d.", errCode);
797     }
798     HILOGI("BackupExtensionAbulity(JS) GetBackupInfo end.");
799     return errCode;
800 }
801 
InvokeJsMethod(CallJsParam * param,AbilityRuntime::HandleEscape & handleEscape,napi_env env,napi_handle_scope & scope,vector<napi_value> & argv)802 static int InvokeJsMethod(CallJsParam *param, AbilityRuntime::HandleEscape& handleEscape, napi_env env,
803     napi_handle_scope& scope, vector<napi_value>& argv)
804 {
805     if (param == nullptr || param->jsObj == nullptr) {
806         HILOGE("param or jsObj is nullptr");
807         return EINVAL;
808     }
809     napi_value value = param->jsObj->GetNapiValue();
810     if (value == nullptr) {
811         HILOGE("failed to get napi value object.");
812         return EINVAL;
813     }
814     napi_status status;
815     napi_value method;
816     status = napi_get_named_property(env, value, param->funcName.c_str(), &method);
817     if (status != napi_ok || param->retParser == nullptr) {
818         HILOGE("ResultValueParser must not null.");
819         return EINVAL;
820     }
821     napi_value result;
822     HILOGI("Extension start do call current js method, methodName:%{public}s", param->funcName.c_str());
823     if (napi_call_function(env, value, method, argv.size(), argv.data(), &result) != napi_ok) {
824         HILOGE("napi call function failed");
825     }
826     if (!param->retParser(env, handleEscape.Escape(result))) {
827         HILOGE("Parser js result fail.");
828         return EINVAL;
829     }
830     return ERR_OK;
831 }
832 
DoCallJsMethod(CallJsParam * param)833 static int DoCallJsMethod(CallJsParam *param)
834 {
835     if (param == nullptr) {
836         HILOGE("param is nullptr");
837         return EINVAL;
838     }
839     AbilityRuntime::JsRuntime *jsRuntime = param->jsRuntime;
840     HILOGI("Start execute DoCallJsMethod");
841     if (jsRuntime == nullptr) {
842         HILOGE("failed to get jsRuntime");
843         return EINVAL;
844     }
845     AbilityRuntime::HandleEscape handleEscape(*jsRuntime);
846     auto env = jsRuntime->GetNapiEnv();
847     napi_handle_scope scope = nullptr;
848     napi_open_handle_scope(env, &scope);
849     if (scope == nullptr) {
850         HILOGE("scope is nullptr");
851         return EINVAL;
852     }
853     vector<napi_value> argv = {};
854     if (param->argParser != nullptr) {
855         if (!param->argParser(env, argv)) {
856             HILOGE("failed to get params.");
857             napi_close_handle_scope(env, scope);
858             return EINVAL;
859         }
860     }
861     auto ret = InvokeJsMethod(param, handleEscape, env, scope, argv);
862     napi_close_handle_scope(env, scope);
863     HILOGI("End execute DoCallJsMethod");
864     return ret;
865 }
866 
CallJsMethod(const std::string & funcName,AbilityRuntime::JsRuntime & jsRuntime,NativeReference * jsObj,InputArgsParser argParser,ResultValueParser retParser)867 int ExtBackupJs::CallJsMethod(const std::string &funcName,
868                               AbilityRuntime::JsRuntime &jsRuntime,
869                               NativeReference *jsObj,
870                               InputArgsParser argParser,
871                               ResultValueParser retParser)
872 {
873     uv_loop_s *loop = nullptr;
874     napi_status status = napi_get_uv_event_loop(jsRuntime.GetNapiEnv(), &loop);
875     if (status != napi_ok) {
876         HILOGE("failed to get uv event loop.");
877         return EINVAL;
878     }
879     auto param = std::make_shared<CallJsParam>(funcName, &jsRuntime, jsObj, argParser, retParser);
880     BExcepUltils::BAssert(param, BError::Codes::EXT_BROKEN_FRAMEWORK, "failed to new param.");
881 
882     auto work = std::make_shared<uv_work_t>();
883     BExcepUltils::BAssert(work, BError::Codes::EXT_BROKEN_FRAMEWORK, "failed to new uv_work_t.");
884 
885     work->data = reinterpret_cast<void *>(param.get());
886     HILOGI("Will execute current js method");
887     auto task = [work {work.get()}]() {
888         if (work == nullptr) {
889             HILOGE("failed to get work.");
890             return;
891         }
892         HILOGI("AsyncWork Enter, %{public}zu", (size_t)work);
893         CallJsParam *param = reinterpret_cast<CallJsParam *>(work->data);
894         do {
895             if (param == nullptr) {
896                 HILOGE("failed to get CallJsParam.");
897                 break;
898             }
899             HILOGI("Start call current js method");
900             if (DoCallJsMethod(param) != ERR_OK) {
901                 HILOGE("failed to call DoCallJsMethod.");
902             }
903         } while (false);
904         HILOGI("will notify current thread info");
905         std::unique_lock<std::mutex> lock(param->backupOperateMutex);
906         param->isReady.store(true);
907         param->backupOperateCondition.notify_all();
908     };
909     auto ret = napi_send_event(jsRuntime.GetNapiEnv(), task, napi_eprio_high);
910     if (ret != napi_status::napi_ok) {
911         HILOGE("failed to napi_send_event, ret:%{public}d.", ret);
912         return EINVAL;
913     }
914     HILOGI("Wait execute current js method");
915     std::unique_lock<std::mutex> lock(param->backupOperateMutex);
916     param->backupOperateCondition.wait(lock, [param]() { return param->isReady.load(); });
917     HILOGI("End do call current js method");
918     return ERR_OK;
919 }
920 
ParseBackupExInfo()921 std::function<bool(napi_env env, std::vector<napi_value> &argv)> ExtBackupJs::ParseBackupExInfo()
922 {
923     auto onBackupExFun = [backupExtInfo(backupExtInfo_)](napi_env env, vector<napi_value> &argv) -> bool {
924         napi_value backupExtInfoVal = nullptr;
925         napi_create_object(env, &backupExtInfoVal);
926         HILOGI("backupExtInfo is:%{public}s", GetAnonyString(backupExtInfo).c_str());
927         if (napi_create_string_utf8(env, backupExtInfo.c_str(), backupExtInfo.size(), &backupExtInfoVal) != napi_ok) {
928             HILOGE("create napi string failed");
929             return false;
930         }
931         argv.emplace_back(backupExtInfoVal);
932         return true;
933     };
934     return onBackupExFun;
935 }
936 
ParseRestoreExInfo()937 std::function<bool(napi_env env, std::vector<napi_value> &argv)> ExtBackupJs::ParseRestoreExInfo()
938 {
939     auto onRestoreExFun = [appVersionCode(appVersionCode_), appVersionStr(appVersionStr_),
940         restoreExtInfo(restoreExtInfo_)](napi_env env, vector<napi_value> &argv) -> bool {
941         HILOGI("restoreExtInfo is:%{public}s", GetAnonyString(restoreExtInfo).c_str());
942         napi_value objValue = nullptr;
943         napi_value restoreRetValue = nullptr;
944         napi_create_object(env, &objValue);
945         napi_create_object(env, &restoreRetValue);
946         napi_set_named_property(env, objValue, "code", AbilityRuntime::CreateJsValue(env, appVersionCode));
947         napi_set_named_property(env, objValue, "name", AbilityRuntime::CreateJsValue(env, appVersionStr.c_str()));
948         if (napi_create_string_utf8(env, restoreExtInfo.c_str(), restoreExtInfo.size(), &restoreRetValue) != napi_ok) {
949             HILOGE("create napi string failed");
950             return false;
951         }
952         argv.emplace_back(objValue);
953         argv.emplace_back(restoreRetValue);
954         return true;
955     };
956     return onRestoreExFun;
957 }
958 
ParseRestoreInfo()959 std::function<bool(napi_env env, std::vector<napi_value> &argv)> ExtBackupJs::ParseRestoreInfo()
960 {
961     auto onRestoreFun = [appVersionCode(appVersionCode_), appVersionStr(appVersionStr_)](napi_env env,
962         vector<napi_value> &argv) -> bool {
963         std::string appVersionStrFlag = appVersionStr;
964         int64_t appVersionCodeFlag = appVersionCode;
965         napi_value objValue = nullptr;
966         napi_create_object(env, &objValue);
967         auto pos = appVersionStrFlag.find_first_of(BConstants::VERSION_NAME_SEPARATOR_CHAR);
968         std::string appVersionFlag = "";
969         if (pos != string::npos) {
970             appVersionFlag = appVersionStrFlag.substr(0, pos);
971             if (appVersionFlag == BConstants::DEFAULT_VERSION_NAME) {
972                 appVersionStrFlag = appVersionFlag;
973                 appVersionCodeFlag = 0;
974             }
975         }
976         napi_set_named_property(env, objValue, "code", AbilityRuntime::CreateJsValue(env, appVersionCodeFlag));
977         napi_set_named_property(env, objValue, "name", AbilityRuntime::CreateJsValue(env, appVersionStrFlag.c_str()));
978         argv.emplace_back(objValue);
979         return true;
980     };
981     return onRestoreFun;
982 }
983 
InvokeAppExtMethod(ErrCode errCode,const std::string result)984 ErrCode ExtBackupJs::InvokeAppExtMethod(ErrCode errCode, const std::string result)
985 {
986     HILOGI("Start Get onBackupEx/onRestoreEx method result, errCode: %{public}d, result: %{public}s",
987         errCode, result.c_str());
988     if ((result.size() == 0) && (errCode == BError(BError::Codes::OK))) {
989         callExtDefaultFunc_.store(true);
990     } else {
991         callExtDefaultFunc_.store(false);
992     }
993     callJsExMethodDone_.store(true);
994     callJsCon_.notify_one();
995     HILOGI("End Get App onBackupEx/onRestoreEx method result");
996     return ERR_OK;
997 }
998 
OnProcess(std::function<void (ErrCode,const std::string)> callback)999 ErrCode ExtBackupJs::OnProcess(std::function<void(ErrCode, const std::string)> callback)
1000 {
1001     HILOGI("BackupExtensionAbility(JS) OnProcess begin.");
1002     BExcepUltils::BAssert(jsObj_, BError::Codes::EXT_BROKEN_FRAMEWORK,
1003                           "The app does not provide the OnProcess interface.");
1004     onProcessCallback_ = std::make_shared<OnProcessCallBackInfo>(callback);
1005     auto retParser = [jsRuntime {&jsRuntime_}, callBackInfo {onProcessCallback_}](napi_env env,
1006         napi_value result) -> bool {
1007             string processStr;
1008             bool isExceptionPending;
1009             napi_is_exception_pending(env, &isExceptionPending);
1010             HILOGI("napi exception pending = %{public}d.", isExceptionPending);
1011             if (!callBackInfo) {
1012                 HILOGE("callbackInfo is nullptr");
1013                 return false;
1014             }
1015             if (isExceptionPending) {
1016                 napi_value exception;
1017                 napi_get_and_clear_last_exception(env, &exception);
1018                 callBackInfo->onProcessCallback(BError(BError::Codes::EXT_THROW_EXCEPTION), processStr);
1019             } else {
1020                 DealNapiStrValue(env, result, processStr);
1021                 callBackInfo->onProcessCallback(BError(BError::Codes::OK), processStr);
1022             }
1023             return true;
1024     };
1025     auto errCode = CallJsMethod("onProcess", jsRuntime_, jsObj_.get(), {}, retParser);
1026     if (errCode != ERR_OK) {
1027         HILOGE("CallJsMethod error, code:%{public}d.", errCode);
1028     }
1029     HILOGI("BackupExtensionAbulity(JS) OnProcess end.");
1030     return errCode;
1031 }
1032 
InitTempPath(const std::string & bundleName)1033 void ExtBackupJs::InitTempPath(const std::string &bundleName)
1034 {
1035     std::string el2BackupDir(BConstants::PATH_BUNDLE_BACKUP_HOME);
1036     if (access(el2BackupDir.c_str(), F_OK) != 0) {
1037         HILOGW("backup home el2 dir not exits, try to create");
1038         if (!ForceCreateDirectory(el2BackupDir.data())) {
1039             HILOGE("Failed to create directory, err = %{public}d", errno);
1040             AppRadar::Info info(bundleName, "", "Create backup home el2 dir failed");
1041             AppRadar::GetInstance().RecordDefaultFuncRes(info, "ExtBackupJs::InitTempPath",
1042                 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_DEFAULT,
1043                 static_cast<int32_t>(BError::Codes::EXT_CREATE_DIR_ERROR));
1044         }
1045     }
1046     std::string el1BackupDir(BConstants::PATH_BUNDLE_BACKUP_HOME_EL1);
1047     if (access(el1BackupDir.c_str(), F_OK) != 0) {
1048         HILOGW("backup home el1 dir not exits, try to create");
1049         if (!ForceCreateDirectory(el1BackupDir.data())) {
1050             HILOGE("Failed to create home el1 dir, err = %{public}d", errno);
1051             AppRadar::Info info(bundleName, "", "Create backup home el1 dir failed");
1052             AppRadar::GetInstance().RecordDefaultFuncRes(info, "ExtBackupJs::InitTempPath",
1053                 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_DEFAULT,
1054                 static_cast<int32_t>(BError::Codes::EXT_CREATE_DIR_ERROR));
1055         }
1056     }
1057 }
1058 } // namespace OHOS::FileManagement::Backup
1059