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