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
BackupRestoreCallback(napi_env env,LibN::NVal thisPtr,LibN::NVal cb)25 BackupRestoreCallback::BackupRestoreCallback(napi_env env, LibN::NVal thisPtr, LibN::NVal cb) : env_(env)
26 {
27 ctx_ = new LibN::NAsyncContextCallback(thisPtr, cb);
28 }
29
~BackupRestoreCallback()30 BackupRestoreCallback::~BackupRestoreCallback()
31 {
32 if (!ctx_) {
33 return;
34 }
35
36 unique_ptr<LibN::NAsyncContextCallback> ptr(ctx_);
37 uv_loop_s *loop = nullptr;
38 napi_status status = napi_get_uv_event_loop(env_, &loop);
39 if (status != napi_ok) {
40 HILOGE("Failed to get uv event loop");
41 ptr->cb_.CleanJsEnv();
42 return;
43 }
44
45 auto work = make_unique<uv_work_t>();
46 if (work == nullptr) {
47 HILOGE("Failed to new uv_work_t");
48 return;
49 }
50 work->data = static_cast<void *>(ctx_);
51
52 int ret = uv_queue_work(
53 loop, work.get(), [](uv_work_t *work) {},
54 [](uv_work_t *work, int status) {
55 LibN::NAsyncContextCallback *ctx = static_cast<LibN::NAsyncContextCallback *>(work->data);
56 delete ctx;
57 delete work;
58 });
59 if (ret) {
60 HILOGE("Failed to call uv_queue_work %{public}d", status);
61 return;
62 }
63 ptr.release();
64 work.release();
65 ctx_ = nullptr;
66 }
67
68 BackupRestoreCallback::operator bool() const
69 {
70 return bool(ctx_->cb_);
71 }
72
DoCallJsMethod(napi_env env,void * data,InputArgsParser argParser)73 static void DoCallJsMethod(napi_env env, void *data, InputArgsParser argParser)
74 {
75 HILOGI("Start execute DoCallJsMethod");
76 napi_handle_scope scope = nullptr;
77 napi_open_handle_scope(env, &scope);
78 if (scope == nullptr) {
79 HILOGE("scope is nullptr");
80 return;
81 }
82 auto ctx = static_cast<LibN::NAsyncContextCallback *>(data);
83 if (ctx == nullptr) {
84 HILOGE("This pointer address is empty");
85 napi_close_handle_scope(env, scope);
86 return;
87 }
88 vector<napi_value> argv = {};
89 if (argParser != nullptr) {
90 if (!argParser(env, argv)) {
91 HILOGE("failed to get params.");
92 napi_close_handle_scope(env, scope);
93 return;
94 }
95 }
96 napi_value global = nullptr;
97 napi_get_global(env, &global);
98 napi_value callback = ctx->cb_.Deref(env).val_;
99 napi_value result = nullptr;
100 napi_status status = napi_call_function(env, global, callback, argv.size(), argv.data(), &result);
101 if (status != napi_ok) {
102 HILOGE("Failed to call function for %{public}d.", status);
103 }
104 napi_close_handle_scope(env, scope);
105 HILOGI("End execute DoCallJsMethod");
106 }
107
CallJsMethod(InputArgsParser argParser)108 void BackupRestoreCallback::CallJsMethod(InputArgsParser argParser)
109 {
110 HILOGI("call BackupRestoreCallback CallJsMethod begin.");
111 uv_loop_s *loop = nullptr;
112 napi_status status = napi_get_uv_event_loop(env_, &loop);
113 if (status != napi_ok) {
114 HILOGE("failed to get uv event loop.");
115 return;
116 }
117 auto workArgs = make_shared<WorkArgs>();
118 auto work = make_unique<uv_work_t>();
119 if (workArgs == nullptr || work == nullptr) {
120 HILOGE("failed to new workArgs or uv_work_t.");
121 return;
122 }
123 workArgs->ptr = this;
124 workArgs->argParser = argParser;
125 work->data = reinterpret_cast<void *>(workArgs.get());
126 HILOGI("Will execute current js method");
127 int ret = uv_queue_work(
128 loop, work.get(), [](uv_work_t *work) {},
129 [](uv_work_t *work, int status) {
130 auto workArgs = reinterpret_cast<WorkArgs *>(work->data);
131 do {
132 if (workArgs == nullptr) {
133 HILOGE("failed to get workArgs.");
134 break;
135 }
136 DoCallJsMethod(workArgs->ptr->env_, workArgs->ptr->ctx_, workArgs->argParser);
137 } while (false);
138 HILOGI("will notify current thread info");
139 std::unique_lock<std::mutex> lock(workArgs->callbackMutex);
140 workArgs->isReady.store(true);
141 workArgs->callbackCondition.notify_all();
142 delete work;
143 });
144 if (ret != 0) {
145 HILOGE("failed to exec uv_queue_work.");
146 work.reset();
147 return;
148 }
149 std::unique_lock<std::mutex> lock(workArgs->callbackMutex);
150 HILOGI("Wait execute callback method end");
151 workArgs->callbackCondition.wait(lock, [workArgs]() { return workArgs->isReady.load(); });
152 work.release();
153 HILOGI("call BackupRestoreCallback CallJsMethod end.");
154 }
155 } // namespace OHOS::FileManagement::Backup