• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "cloud_sync_napi.h"
17 
18 #include <sys/types.h>
19 
20 #include "cloud_sync_manager.h"
21 #include "dfs_error.h"
22 #include "utils_log.h"
23 #include "async_work.h"
24 #include "uv.h"
25 
26 namespace OHOS::FileManagement::CloudSync {
27 using namespace FileManagement::LibN;
28 using namespace std;
29 
CloudSyncCallbackImpl(napi_env env,napi_value fun)30 CloudSyncCallbackImpl::CloudSyncCallbackImpl(napi_env env, napi_value fun) : env_(env)
31 {
32     if (fun != nullptr) {
33         napi_create_reference(env_, fun, 1, &cbOnRef_);
34     }
35 }
36 
OnComplete(UvChangeMsg * msg)37 void CloudSyncCallbackImpl::OnComplete(UvChangeMsg *msg)
38 {
39     auto cloudSyncCallback = msg->cloudSyncCallback_.lock();
40     if (cloudSyncCallback == nullptr || cloudSyncCallback->cbOnRef_ == nullptr) {
41         LOGE("cloudSyncCallback->cbOnRef_ is nullptr");
42         return;
43     }
44     auto env = cloudSyncCallback->env_;
45     auto ref = cloudSyncCallback->cbOnRef_;
46     napi_handle_scope scope = nullptr;
47     napi_open_handle_scope(env, &scope);
48     napi_value jsCallback = nullptr;
49     napi_status status = napi_get_reference_value(env, ref, &jsCallback);
50     if (status != napi_ok) {
51         LOGE("Create reference failed, status: %{public}d", status);
52         napi_close_handle_scope(env, scope);
53         return;
54     }
55     NVal obj = NVal::CreateObject(env);
56     obj.AddProp("state", NVal::CreateInt32(env, (int32_t)msg->state_).val_);
57     obj.AddProp("error", NVal::CreateInt32(env, (int32_t)msg->error_).val_);
58     napi_value retVal = nullptr;
59     napi_value global = nullptr;
60     napi_get_global(env, &global);
61     status = napi_call_function(env, global, jsCallback, ARGS_ONE, &(obj.val_), &retVal);
62     if (status != napi_ok) {
63         LOGE("napi call function failed, status: %{public}d", status);
64     }
65     napi_close_handle_scope(env, scope);
66 }
67 
OnSyncStateChanged(CloudSyncState state,ErrorType error)68 void CloudSyncCallbackImpl::OnSyncStateChanged(CloudSyncState state, ErrorType error)
69 {
70     uv_loop_s *loop = nullptr;
71     napi_get_uv_event_loop(env_, &loop);
72     if (loop == nullptr) {
73         return;
74     }
75 
76     uv_work_t *work = new (nothrow) uv_work_t;
77     if (work == nullptr) {
78         LOGE("Failed to create uv work");
79         return;
80     }
81 
82     UvChangeMsg *msg = new (std::nothrow) UvChangeMsg(shared_from_this(), state, error);
83     if (msg == nullptr) {
84         delete work;
85         return;
86     }
87 
88     work->data = reinterpret_cast<void *>(msg);
89     int ret = uv_queue_work(
90         loop, work, [](uv_work_t *work) {},
91         [](uv_work_t *work, int status) {
92             auto msg = reinterpret_cast<UvChangeMsg *>(work->data);
93             OnComplete(msg);
94             delete msg;
95             delete work;
96         });
97     if (ret != 0) {
98         LOGE("Failed to execute libuv work queue, ret: %{public}d", ret);
99         delete msg;
100         delete work;
101     }
102 }
103 
DeleteReference()104 void CloudSyncCallbackImpl::DeleteReference()
105 {
106     if (cbOnRef_ != nullptr) {
107         napi_delete_reference(env_, cbOnRef_);
108         cbOnRef_ = nullptr;
109     }
110 }
111 
OnSyncStateChanged(SyncType type,SyncPromptState state)112 void CloudSyncCallbackImpl::OnSyncStateChanged(SyncType type, SyncPromptState state)
113 {
114     return;
115 }
116 
Constructor(napi_env env,napi_callback_info info)117 napi_value CloudSyncNapi::Constructor(napi_env env, napi_callback_info info)
118 {
119     NFuncArg funcArg(env, info);
120     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
121         NError(E_PARAMS).ThrowErr(env, "Number of arguments unmatched");
122         return nullptr;
123     }
124 
125     return funcArg.GetThisVar();
126 }
127 
OnCallback(napi_env env,napi_callback_info info)128 napi_value CloudSyncNapi::OnCallback(napi_env env, napi_callback_info info)
129 {
130     NFuncArg funcArg(env, info);
131     if (!funcArg.InitArgs(NARG_CNT::TWO)) {
132         NError(E_PARAMS).ThrowErr(env, "Number of arguments unmatched");
133         LOGE("OnCallback Number of arguments unmatched");
134         return nullptr;
135     }
136 
137     auto [succ, type, ignore] = NVal(env, funcArg[(int)NARG_POS::FIRST]).ToUTF8String();
138     if (!(succ && (type.get() == std::string("progress")))) {
139         NError(E_PARAMS).ThrowErr(env);
140         return nullptr;
141     }
142 
143     if (!NVal(env, funcArg[(int)NARG_POS::SECOND]).TypeIs(napi_function)) {
144         LOGE("Argument type mismatch");
145         NError(E_PARAMS).ThrowErr(env);
146         return nullptr;
147     }
148 
149     if (callback_ != nullptr) {
150         LOGI("callback already exist");
151         return NVal::CreateUndefined(env).val_;
152     }
153 
154     callback_ = make_shared<CloudSyncCallbackImpl>(env, NVal(env, funcArg[(int)NARG_POS::SECOND]).val_);
155     int32_t ret = CloudSyncManager::GetInstance().RegisterCallback(callback_);
156     if (ret != E_OK) {
157         LOGE("OnCallback Register error, result: %{public}d", ret);
158         NError(Convert2JsErrNum(ret)).ThrowErr(env);
159         return nullptr;
160     }
161 
162     return NVal::CreateUndefined(env).val_;
163 }
164 
OffCallback(napi_env env,napi_callback_info info)165 napi_value CloudSyncNapi::OffCallback(napi_env env, napi_callback_info info)
166 {
167     NFuncArg funcArg(env, info);
168     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
169         NError(E_PARAMS).ThrowErr(env, "Number of arguments unmatched");
170         LOGE("OffCallback Number of arguments unmatched");
171         return nullptr;
172     }
173 
174     auto [succ, type, ignore] = NVal(env, funcArg[(int)NARG_POS::FIRST]).ToUTF8String();
175     if (!(succ && (type.get() == std::string("progress")))) {
176         NError(E_PARAMS).ThrowErr(env);
177         return nullptr;
178     }
179 
180     if (funcArg.GetArgc() == (uint)NARG_CNT::TWO && !NVal(env, funcArg[(int)NARG_POS::SECOND]).TypeIs(napi_function)) {
181         LOGE("Argument type mismatch");
182         NError(E_PARAMS).ThrowErr(env);
183         return nullptr;
184     }
185 
186     int32_t ret = CloudSyncManager::GetInstance().UnRegisterCallback();
187     if (ret != E_OK) {
188         LOGE("OffCallback UnRegister error, result: %{public}d", ret);
189         NError(Convert2JsErrNum(ret)).ThrowErr(env);
190         return nullptr;
191     }
192     if (callback_ != nullptr) {
193         /* napi delete reference */
194         callback_->DeleteReference();
195         callback_ = nullptr;
196     }
197     return NVal::CreateUndefined(env).val_;
198 }
199 
Start(napi_env env,napi_callback_info info)200 napi_value CloudSyncNapi::Start(napi_env env, napi_callback_info info)
201 {
202     NFuncArg funcArg(env, info);
203     if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
204         NError(E_PARAMS).ThrowErr(env);
205     }
206 
207     auto cbExec = []() -> NError {
208         int32_t ret = CloudSyncManager::GetInstance().StartSync();
209         if (ret != E_OK) {
210             LOGE("Start Sync error, result: %{public}d", ret);
211             return NError(Convert2JsErrNum(ret));
212         }
213         return NError(ERRNO_NOERR);
214     };
215 
216     auto cbComplete = [](napi_env env, NError err) -> NVal {
217         if (err) {
218             return {env, err.GetNapiErr(env)};
219         }
220         return NVal::CreateUndefined(env);
221     };
222 
223     std::string procedureName = "Start";
224     auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, static_cast<size_t>(NARG_CNT::TWO));
225     return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbComplete).val_;
226 }
227 
Stop(napi_env env,napi_callback_info info)228 napi_value CloudSyncNapi::Stop(napi_env env, napi_callback_info info)
229 {
230     NFuncArg funcArg(env, info);
231     if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
232         NError(E_PARAMS).ThrowErr(env);
233         return nullptr;
234     }
235 
236     auto cbExec = []() -> NError {
237         int32_t ret = CloudSyncManager::GetInstance().StopSync();
238         if (ret != E_OK) {
239             LOGE("Stop Sync error, result: %{public}d", ret);
240             return NError(Convert2JsErrNum(ret));
241         }
242         return NError(ERRNO_NOERR);
243     };
244 
245     auto cbComplete = [](napi_env env, NError err) -> NVal {
246         if (err) {
247             return {env, err.GetNapiErr(env)};
248         }
249         return NVal::CreateUndefined(env);
250     };
251 
252     std::string procedureName = "Stop";
253     auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, static_cast<size_t>(NARG_CNT::TWO));
254     return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbComplete).val_;
255 }
256 
SetClassName(const std::string classname)257 void CloudSyncNapi::SetClassName(const std::string classname)
258 {
259     className_ = classname;
260 }
261 
GetClassName()262 std::string CloudSyncNapi::GetClassName()
263 {
264     return className_;
265 }
266 
ToExport(std::vector<napi_property_descriptor> props)267 bool CloudSyncNapi::ToExport(std::vector<napi_property_descriptor> props)
268 {
269     std::string className = GetClassName();
270     auto [succ, classValue] =
271         NClass::DefineClass(exports_.env_, className, Constructor, std::move(props));
272     if (!succ) {
273         NError(E_GETRESULT).ThrowErr(exports_.env_);
274         LOGE("Failed to define CloudSyncNapi class");
275         return false;
276     }
277 
278     succ = NClass::SaveClass(exports_.env_, className, classValue);
279     if (!succ) {
280         NError(E_GETRESULT).ThrowErr(exports_.env_);
281         LOGE("Failed to save CloudSyncNapi class");
282         return false;
283     }
284 
285     return exports_.AddProp(className, classValue);
286 }
287 
Export()288 bool CloudSyncNapi::Export()
289 {
290     std::vector<napi_property_descriptor> props = {
291         NVal::DeclareNapiFunction("on", OnCallback),
292         NVal::DeclareNapiFunction("off", OffCallback),
293         NVal::DeclareNapiFunction("start", Start),
294         NVal::DeclareNapiFunction("stop", Stop),
295     };
296     std::string className = GetClassName();
297     auto [succ, classValue] =
298         NClass::DefineClass(exports_.env_, className, CloudSyncNapi::Constructor, std::move(props));
299     if (!succ) {
300         NError(E_GETRESULT).ThrowErr(exports_.env_);
301         LOGE("Failed to define GallerySync class");
302         return false;
303     }
304 
305     succ = NClass::SaveClass(exports_.env_, className, classValue);
306     if (!succ) {
307         NError(E_GETRESULT).ThrowErr(exports_.env_);
308         LOGE("Failed to save GallerySync class");
309         return false;
310     }
311 
312     return exports_.AddProp(className, classValue);
313 }
314 
315 } // namespace OHOS::FileManagement::CloudSync
316