1 /*
2 * Copyright (c) 2024-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
16 #include "uv.h"
17 #include "native_reference.h"
18 #include "native_value.h"
19 #include "b_error/b_error.h"
20 #include "general_callbacks.h"
21
22 namespace OHOS::FileManagement::Backup {
23 using namespace std;
24
RemoveCallbackRef()25 void GeneralCallbacks::RemoveCallbackRef()
26 {
27 HILOGI("Called RemoveCallbackRef");
28 onFileReady.CleanRef();
29 onBundleBegin.CleanRef();
30 onBundleEnd.CleanRef();
31 onAllBundlesEnd.CleanRef();
32 onBackupServiceDied.CleanRef();
33 onResultReport.CleanRef();
34 onProcess.CleanRef();
35 }
36
CleanRef()37 void BackupRestoreCallback::CleanRef()
38 {
39 HILOGI("BackupRestoreCallback CleanRef");
40 if (!ctx_) {
41 HILOGE("BackupRestoreCallback ctx is nullptr");
42 return;
43 }
44 if (!bool(ctx_->cb_)) {
45 HILOGE("BackupRestoreCallback ref is nullptr");
46 return;
47 }
48 ctx_->cb_.DeleteJsEnv();
49 }
50
BackupRestoreCallback(napi_env env,LibN::NVal thisPtr,LibN::NVal cb)51 BackupRestoreCallback::BackupRestoreCallback(napi_env env, LibN::NVal thisPtr, LibN::NVal cb) : env_(env)
52 {
53 ctx_ = new LibN::NAsyncContextCallback(thisPtr, cb);
54 }
55
~BackupRestoreCallback()56 BackupRestoreCallback::~BackupRestoreCallback()
57 {
58 HILOGI("BackupRestoreCallback destruct start");
59 if (!ctx_) {
60 HILOGE("BackupRestoreCallback ctx is nullptr");
61 return;
62 }
63
64 unique_ptr<LibN::NAsyncContextCallback> ptr(ctx_);
65 auto task = [](void* ptr) ->void {
66 auto ctx = reinterpret_cast<LibN::NAsyncContextCallback *>(ptr);
67 if (ctx == nullptr) {
68 HILOGE("failed to get ctx.");
69 return;
70 }
71 HILOGI("BackupRestoreCallback destruct delete ctx");
72 if (bool(ctx->cb_)) {
73 ctx->cb_.CleanJsEnv();
74 }
75 delete ctx;
76 };
77 uint64_t handleId = 0;
78 auto ret = napi_send_cancelable_event(env_, task, ptr.get(), napi_eprio_high, &handleId, "destructor");
79 if (ret != napi_status::napi_ok) {
80 HILOGE("failed to napi_send_cancelable_event, ret:%{public}d, name:%{public}s.", ret, "destructor");
81 if (bool(ctx_->cb_)) {
82 ctx_->cb_.CleanJsEnv();
83 }
84 return;
85 }
86 ptr.release();
87 ctx_ = nullptr;
88 HILOGI("BackupRestoreCallback destruct end");
89 }
90
operator bool() const91 BackupRestoreCallback::operator bool() const
92 {
93 return bool(ctx_->cb_);
94 }
95
DoCallJsMethod(napi_env env,void * data,InputArgsParser argParser)96 static void DoCallJsMethod(napi_env env, void *data, InputArgsParser argParser)
97 {
98 HILOGI("Start execute DoCallJsMethod");
99 napi_handle_scope scope = nullptr;
100 napi_open_handle_scope(env, &scope);
101 if (scope == nullptr) {
102 HILOGE("scope is nullptr");
103 return;
104 }
105 auto ctx = static_cast<LibN::NAsyncContextCallback *>(data);
106 if (ctx == nullptr) {
107 HILOGE("This pointer address is empty");
108 napi_close_handle_scope(env, scope);
109 return;
110 }
111 vector<napi_value> argv = {};
112 if (argParser != nullptr) {
113 if (!argParser(env, argv)) {
114 HILOGE("failed to get params.");
115 napi_close_handle_scope(env, scope);
116 return;
117 }
118 }
119 napi_value global = nullptr;
120 napi_get_global(env, &global);
121 if (!bool(ctx->cb_)) {
122 HILOGE("Failed to get ref.");
123 napi_close_handle_scope(env, scope);
124 return;
125 }
126 napi_value callback = ctx->cb_.Deref(env).val_;
127 napi_value result = nullptr;
128 napi_status status = napi_call_function(env, global, callback, argv.size(), argv.data(), &result);
129 if (status != napi_ok) {
130 HILOGE("Failed to call function for %{public}d.", status);
131 }
132 napi_close_handle_scope(env, scope);
133 HILOGI("End execute DoCallJsMethod");
134 }
135
CallJsMethod(InputArgsParser argParser)136 void BackupRestoreCallback::CallJsMethod(InputArgsParser argParser)
137 {
138 HILOGI("call BackupRestoreCallback CallJsMethod begin.");
139 auto workArgs = make_shared<WorkArgs>();
140 if (workArgs == nullptr) {
141 HILOGE("failed to new workArgs or uv_work_t.");
142 return;
143 }
144 workArgs->ptr = this;
145 workArgs->argParser = argParser;
146 HILOGI("Will execute current js method");
147 auto task = [](void* ptr) ->void {
148 auto workArgs = reinterpret_cast<WorkArgs *>(ptr);
149 do {
150 if (workArgs == nullptr) {
151 HILOGE("failed to get workArgs.");
152 break;
153 }
154 DoCallJsMethod(workArgs->ptr->env_, workArgs->ptr->ctx_, workArgs->argParser);
155 } while (false);
156 HILOGI("will notify current thread info");
157 std::unique_lock<std::mutex> lock(workArgs->callbackMutex);
158 workArgs->isReady.store(true);
159 workArgs->callbackCondition.notify_all();
160 };
161 uint64_t handleId = 0;
162 auto ret = napi_send_cancelable_event(env_, task, workArgs.get(), napi_eprio_high, &handleId, "jsmethod");
163 if (ret != napi_status::napi_ok) {
164 HILOGE("failed to napi_send_cancelable_event, ret:%{public}d, name:%{public}s.", ret, "jsmethod");
165 return;
166 }
167 std::unique_lock<std::mutex> lock(workArgs->callbackMutex);
168 HILOGI("Wait execute callback method end");
169 workArgs->callbackCondition.wait(lock, [workArgs]() { return workArgs->isReady.load(); });
170 HILOGI("call BackupRestoreCallback CallJsMethod end.");
171 }
172 } // namespace OHOS::FileManagement::Backup