1 /*
2 * Copyright (c) 2023-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 "cloud_file_cache_napi.h"
17
18 #include <cstddef>
19 #include <memory>
20 #include <mutex>
21 #include <sys/types.h>
22 #include <unordered_set>
23
24 #include "async_work.h"
25 #include "cloud_sync_manager.h"
26 #include "dfs_error.h"
27 #include "multi_download_progress_napi.h"
28 #include "register_callback_manager_napi.h"
29 #include "utils_log.h"
30
31 namespace OHOS::FileManagement::CloudSync {
32 using namespace FileManagement::LibN;
33 using namespace std;
34
35 static const std::unordered_set<int32_t> errForSingleFileSync = { ENOENT, EACCES, EAGAIN,
36 EINTR, ENOSYS, E_ILLEGAL_URI };
37
StartDownloadInner(const std::string & uri,int32_t fieldKey)38 int32_t CloudFileCacheCallbackImplNapi::StartDownloadInner(const std::string &uri, int32_t fieldKey)
39 {
40 int64_t downloadId = 0;
41 std::lock_guard<std::mutex> lock(downloadInfoMtx_);
42 int32_t ret = CloudSyncManager::GetInstance().StartFileCache({uri}, downloadId, fieldKey, shared_from_this());
43 if (ret != E_OK) {
44 LOGE("Start single download failed! ret = %{public}d", ret);
45 return ret;
46 }
47 downloadInfos_[downloadId] = std::make_shared<SingleProgressNapi>(downloadId);
48 return ret;
49 }
50
StopDownloadInner(const std::string & uri,bool needClean)51 int32_t CloudFileCacheCallbackImplNapi::StopDownloadInner(const std::string &uri, bool needClean)
52 {
53 auto downloadIdList = GetDownloadIdsByUri(uri);
54 int32_t ret = E_OK;
55 int32_t resErr = E_OK;
56 LOGI("Stop Download downloadId list size: %{public}zu", downloadIdList.size());
57 for (auto taskId : downloadIdList) {
58 resErr = CloudSyncManager::GetInstance().StopFileCache(taskId, needClean);
59 if (resErr != E_OK) {
60 ret = resErr;
61 continue;
62 }
63 }
64 if (ret != E_OK) {
65 LOGE("Stop Download failed! ret = %{public}d", ret);
66 }
67 return ret;
68 }
69
StartDownloadInner(const std::vector<std::string> & uriVec,int64_t & downloadId,int32_t fieldKey)70 int32_t CloudFileCacheCallbackImplNapi::StartDownloadInner(const std::vector<std::string> &uriVec,
71 int64_t &downloadId,
72 int32_t fieldKey)
73 {
74 std::lock_guard<std::mutex> lock(downloadInfoMtx_);
75 int32_t ret = CloudSyncManager::GetInstance().StartFileCache(uriVec, downloadId, fieldKey, shared_from_this());
76 if (ret != E_OK) {
77 LOGE("Start batch download failed! ret = %{public}d", ret);
78 return ret;
79 }
80 downloadInfos_[downloadId] = std::make_shared<BatchProgressNapi>(downloadId);
81 return ret;
82 }
83
StopDownloadInner(int64_t downloadId,bool needClean)84 int32_t CloudFileCacheCallbackImplNapi::StopDownloadInner(int64_t downloadId, bool needClean)
85 {
86 int32_t ret = CloudSyncManager::GetInstance().StopFileCache(downloadId, needClean);
87 if (ret != E_OK) {
88 LOGE("Batch stop file cache failed! ret = %{public}d", ret);
89 }
90 return ret;
91 }
92
Constructor(napi_env env,napi_callback_info info)93 napi_value CloudFileCacheNapi::Constructor(napi_env env, napi_callback_info info)
94 {
95 NFuncArg funcArg(env, info);
96 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
97 LOGE("Start Number of arguments unmatched");
98 NError(JsErrCode::E_INNER_FAILED).ThrowErr(env);
99 return nullptr;
100 }
101
102 auto fileCacheEntity = make_unique<FileCacheEntity>();
103 if (!NClass::SetEntityFor<FileCacheEntity>(env, funcArg.GetThisVar(), move(fileCacheEntity))) {
104 LOGE("Failed to set file cache entity.");
105 NError(JsErrCode::E_INNER_FAILED).ThrowErr(env);
106 return nullptr;
107 }
108 return funcArg.GetThisVar();
109 }
110
ToExport(std::vector<napi_property_descriptor> props)111 bool CloudFileCacheNapi::ToExport(std::vector<napi_property_descriptor> props)
112 {
113 std::string className = GetClassName();
114 auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props));
115 if (!succ) {
116 NError(JsErrCode::E_INNER_FAILED).ThrowErr(exports_.env_);
117 LOGE("Failed to define GallerySync class");
118 return false;
119 }
120
121 succ = NClass::SaveClass(exports_.env_, className, classValue);
122 if (!succ) {
123 NError(JsErrCode::E_INNER_FAILED).ThrowErr(exports_.env_);
124 LOGE("Failed to save GallerySync class");
125 return false;
126 }
127
128 return exports_.AddProp(className, classValue);
129 }
130
CleanCloudFileCache(napi_env env,napi_callback_info info)131 napi_value CloudFileCacheNapi::CleanCloudFileCache(napi_env env, napi_callback_info info)
132 {
133 LOGI("CleanCache start");
134 NFuncArg funcArg(env, info);
135
136 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
137 NError(E_PARAMS).ThrowErr(env);
138 return nullptr;
139 }
140
141 auto [succ, uri, ignore] = NVal(env, funcArg[(int)NARG_POS::FIRST]).ToUTF8String();
142 if (!succ) {
143 LOGE("Get uri error");
144 NError(EINVAL).ThrowErr(env);
145 return nullptr;
146 }
147
148 int32_t ret = CloudSyncManager::GetInstance().CleanCache(uri.get());
149 if (ret != E_OK) {
150 NError(Convert2JsErrNum(ret)).ThrowErr(env);
151 return nullptr;
152 }
153 return NVal::CreateUndefined(env).val_;
154 }
155
GetCleanCacheErrPublic(int32_t result)156 static int32_t GetCleanCacheErrPublic(int32_t result)
157 {
158 LOGE("cleanCache failed, errno : %{public}d", result);
159 if (errForSingleFileSync.find(result) != errForSingleFileSync.end()) {
160 return result;
161 }
162 return E_SERVICE_INNER_ERROR;
163 }
164
CleanFileCache(napi_env env,napi_callback_info info)165 napi_value CloudFileCacheNapi::CleanFileCache(napi_env env, napi_callback_info info)
166 {
167 LOGI("CleanCache start");
168 NFuncArg funcArg(env, info);
169
170 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
171 NError(EINVAL).ThrowErr(env);
172 LOGE("Number of arguments unmatched");
173 return nullptr;
174 }
175
176 auto [succ, uri, ignore] = NVal(env, funcArg[(int)NARG_POS::FIRST]).ToUTF8String();
177 if (!succ) {
178 LOGE("CleanFileCache get uri parameter failed!");
179 NError(EINVAL).ThrowErr(env);
180 return nullptr;
181 }
182
183 int32_t ret = CloudSyncManager::GetInstance().CleanFileCache(uri.get());
184 if (ret != E_OK) {
185 int32_t err = GetCleanCacheErrPublic(ret);
186 NError(Convert2JsErrNum(err)).ThrowErr(env);
187 LOGE("CleanFileCache failed, ret:%{public}d", err);
188 return nullptr;
189 }
190 return NVal::CreateUndefined(env).val_;
191 }
192
Export()193 bool CloudFileCacheNapi::Export()
194 {
195 std::vector<napi_property_descriptor> props = {
196 NVal::DeclareNapiFunction("on", CloudFileCacheNapi::On),
197 NVal::DeclareNapiFunction("off", CloudFileCacheNapi::Off),
198 NVal::DeclareNapiFunction("start", CloudFileCacheNapi::StartFileCache),
199 NVal::DeclareNapiFunction("startBatch", CloudFileCacheNapi::StartBatchFileCache),
200 NVal::DeclareNapiFunction("stop", CloudFileCacheNapi::StopFileCache),
201 NVal::DeclareNapiFunction("stopBatch", CloudFileCacheNapi::StopBatchFileCache),
202 NVal::DeclareNapiFunction("cleanCache", CloudFileCacheNapi::CleanCloudFileCache),
203 NVal::DeclareNapiFunction("cleanFileCache", CloudFileCacheNapi::CleanFileCache),
204 };
205
206 return ToExport(props);
207 }
208
GetCallbackImpl(napi_env env,NFuncArg & funcArg,const std::string & eventType,bool isInit)209 static std::shared_ptr<CloudFileCacheCallbackImplNapi> GetCallbackImpl(napi_env env, NFuncArg &funcArg,
210 const std::string &eventType, bool isInit)
211 {
212 auto fileCacheEntity = NClass::GetEntityOf<FileCacheEntity>(env, funcArg.GetThisVar());
213 if (!fileCacheEntity) {
214 LOGE("Failed to get file cache entity.");
215 return nullptr;
216 }
217
218 std::shared_ptr<CloudFileCacheCallbackImplNapi> callbackImpl = nullptr;
219 auto iter = fileCacheEntity->registerMap.find(eventType);
220 if (iter == fileCacheEntity->registerMap.end() || iter->second == nullptr) {
221 if (isInit) {
222 callbackImpl = std::make_shared<CloudFileCacheCallbackImplNapi>(env);
223 fileCacheEntity->registerMap.insert(make_pair(eventType, callbackImpl));
224 }
225 } else {
226 callbackImpl = iter->second;
227 }
228 return callbackImpl;
229 }
230
ParseUriFromParam(napi_env env,NFuncArg & funcArg)231 static std::tuple<int32_t, std::string> ParseUriFromParam(napi_env env, NFuncArg &funcArg)
232 {
233 auto [succ, uri, size] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
234 if (!succ || size == 0) {
235 LOGE("Parse URI from parameter failed!");
236 return {E_PARAMS, ""};
237 }
238 return {E_OK, string(uri.get())};
239 }
240
StartFileCache(napi_env env,napi_callback_info info)241 napi_value CloudFileCacheNapi::StartFileCache(napi_env env, napi_callback_info info)
242 {
243 NFuncArg funcArg(env, info);
244 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
245 LOGE("Start Number of arguments unmatched");
246 NError(E_PARAMS).ThrowErr(env);
247 return nullptr;
248 }
249
250 auto [ret, uri] = ParseUriFromParam(env, funcArg);
251 if (ret != E_OK) {
252 NError(ret).ThrowErr(env);
253 return nullptr;
254 }
255 auto callbackImpl = GetCallbackImpl(env, funcArg, PROGRESS, true);
256 auto cbExec = [uri{uri}, callbackImpl{callbackImpl}]() -> NError {
257 if (callbackImpl == nullptr) {
258 LOGE("Failed to get download callback");
259 return NError(E_PARAMS);
260 }
261 int32_t ret = callbackImpl->StartDownloadInner(uri, FieldKey::FIELDKEY_CONTENT);
262 if (ret != E_OK) {
263 LOGE("Start Download failed! ret = %{public}d", ret);
264 if (ret != E_INVAL_ARG) {
265 ret = E_BROKEN_IPC;
266 }
267 return NError(Convert2JsErrNum(ret));
268 }
269 return NError(ERRNO_NOERR);
270 };
271
272 auto cbCompl = [](napi_env env, NError err) -> NVal {
273 if (err) {
274 return {env, err.GetNapiErr(env)};
275 }
276 return NVal::CreateUndefined(env);
277 };
278
279 string procedureName = "cloudFileCache";
280 auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, static_cast<size_t>(NARG_CNT::TWO));
281 return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbCompl).val_;
282 }
283
GetCleanFlagForStop(napi_env env,NFuncArg & funcArg)284 static tuple<int32_t, bool, bool> GetCleanFlagForStop(napi_env env, NFuncArg &funcArg)
285 {
286 bool succ = true;
287 bool needClean = false;
288 size_t maxArgSize = static_cast<size_t>(NARG_CNT::TWO);
289 if (funcArg.GetArgc() >= NARG_CNT::TWO) {
290 NVal option(env, funcArg[NARG_POS::SECOND]);
291 if (!option.TypeIs(napi_function)) {
292 tie(succ, needClean) = option.ToBool();
293 maxArgSize = static_cast<size_t>(NARG_CNT::THREE);
294 }
295 if (!succ) {
296 LOGE("Failed to get clean flag!");
297 return {EINVAL, false, false};
298 }
299 }
300 return {E_OK, needClean, maxArgSize};
301 }
302
StopFileCache(napi_env env,napi_callback_info info)303 napi_value CloudFileCacheNapi::StopFileCache(napi_env env, napi_callback_info info)
304 {
305 NFuncArg funcArg(env, info);
306 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) {
307 LOGE("Stop Number of arguments unmatched");
308 NError(E_PARAMS).ThrowErr(env);
309 return nullptr;
310 }
311 auto [res, uri] = ParseUriFromParam(env, funcArg);
312 if (res != E_OK) {
313 NError(res).ThrowErr(env);
314 return nullptr;
315 }
316
317 auto [ret, needClean, maxArgSize] = GetCleanFlagForStop(env, funcArg);
318 if (ret != E_OK) {
319 NError(E_PARAMS).ThrowErr(env);
320 return nullptr;
321 }
322 auto callbackImpl = GetCallbackImpl(env, funcArg, PROGRESS, false);
323 auto cbExec = [uri{uri}, needClean{needClean}, callbackImpl{callbackImpl}]() -> NError {
324 if (callbackImpl == nullptr) {
325 LOGE("Failed to get download callback");
326 return NError(E_PARAMS);
327 }
328 int32_t ret = callbackImpl->StopDownloadInner(uri, needClean);
329 if (ret != E_OK) {
330 LOGE("Stop Download failed! ret = %{public}d", ret);
331 if (ret != E_INVAL_ARG) {
332 ret = E_BROKEN_IPC;
333 }
334 return NError(Convert2JsErrNum(ret));
335 }
336 return NError(ERRNO_NOERR);
337 };
338
339 auto cbCompl = [](napi_env env, NError err) -> NVal {
340 if (err) {
341 return {env, err.GetNapiErr(env)};
342 }
343 return NVal::CreateUndefined(env);
344 };
345
346 string procedureName = "cloudFileCache";
347 auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, maxArgSize);
348 return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbCompl).val_;
349 }
350
351 struct FileCacheArg {
352 std::vector<std::string> uriList;
353 int64_t downloadId = 0;
354 std::shared_ptr<CloudFileCacheCallbackImplNapi> callbackImpl = nullptr;
355 int32_t fieldKey = FieldKey::FIELDKEY_CONTENT;
356 };
357
FillParamForBatchStart(napi_env env,NFuncArg & funcArg)358 static std::tuple<int32_t, std::shared_ptr<FileCacheArg>, int32_t> FillParamForBatchStart(napi_env env,
359 NFuncArg &funcArg)
360 {
361 size_t maxArgSize = static_cast<size_t>(NARG_CNT::TWO);
362 auto [succ, uriArray, size] = NVal(env, funcArg[NARG_POS::FIRST]).ToStringArray();
363 if (!succ || size == 0) {
364 LOGE("Start get uri array parameter failed!");
365 return {EINVAL, nullptr, maxArgSize};
366 }
367
368 int32_t fieldKey = 0;
369 if (funcArg.GetArgc() >= NARG_CNT::TWO) {
370 NVal option(env, funcArg[NARG_POS::SECOND]);
371 if (!option.TypeIs(napi_function)) {
372 tie(succ, fieldKey) = option.ToInt32();
373 maxArgSize = static_cast<size_t>(NARG_CNT::THREE);
374 }
375 if (!succ) {
376 LOGE("Failed to get fileType!");
377 return {EINVAL, nullptr, maxArgSize};
378 }
379 }
380
381 auto fileCache = std::make_shared<FileCacheArg>();
382 fileCache->uriList.swap(uriArray);
383 fileCache->fieldKey = fieldKey;
384 fileCache->callbackImpl = GetCallbackImpl(env, funcArg, MULTI_PROGRESS, true);
385 return {E_OK, fileCache, maxArgSize};
386 }
387
StartBatchFileCache(napi_env env,napi_callback_info info)388 napi_value CloudFileCacheNapi::StartBatchFileCache(napi_env env, napi_callback_info info)
389 {
390 NFuncArg funcArg(env, info);
391 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
392 LOGE("Start Number of arguments unmatched");
393 NError(EINVAL).ThrowErr(env);
394 return nullptr;
395 }
396
397 auto [ret, fileCache, maxArgSize] = FillParamForBatchStart(env, funcArg);
398 if (ret != E_OK) {
399 NError(ret).ThrowErr(env);
400 return nullptr;
401 }
402
403 auto cbExec = [fileCache{fileCache}]() -> NError {
404 if (fileCache == nullptr || fileCache->callbackImpl == nullptr) {
405 LOGE("Failed to get download callback");
406 return NError(JsErrCode::E_INNER_FAILED);
407 }
408 int32_t ret =
409 fileCache->callbackImpl->StartDownloadInner(fileCache->uriList, fileCache->downloadId, fileCache->fieldKey);
410 if (ret != E_OK) {
411 ret = (ret == E_CLOUD_SDK) ? E_SERVICE_INNER_ERROR : ret;
412 return NError(Convert2JsErrNum(ret));
413 }
414 return NError(ERRNO_NOERR);
415 };
416
417 auto cbCompl = [fileCache{fileCache}](napi_env env, NError err) -> NVal {
418 if (err) {
419 return {env, err.GetNapiErr(env)};
420 }
421 return NVal::CreateInt64(env, fileCache->downloadId);
422 };
423
424 string procedureName = "cloudFileCache";
425 auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, maxArgSize);
426 return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbCompl).val_;
427 }
428
StopBatchFileCache(napi_env env,napi_callback_info info)429 napi_value CloudFileCacheNapi::StopBatchFileCache(napi_env env, napi_callback_info info)
430 {
431 NFuncArg funcArg(env, info);
432 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) {
433 LOGE("Start Number of arguments unmatched");
434 NError(EINVAL).ThrowErr(env);
435 return nullptr;
436 }
437
438 auto [succ, downloadId] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt64();
439 if (!succ || downloadId <= 0) {
440 LOGE("Start get taskId parameter failed!");
441 NError(EINVAL).ThrowErr(env);
442 return nullptr;
443 }
444
445 auto [ret, needClean, maxArgSize] = GetCleanFlagForStop(env, funcArg);
446 if (ret != E_OK) {
447 NError(ret).ThrowErr(env);
448 return nullptr;
449 }
450 auto callbackImpl = GetCallbackImpl(env, funcArg, MULTI_PROGRESS, false);
451 auto cbExec = [downloadId{downloadId}, needClean{needClean}, callbackImpl{callbackImpl}]() -> NError {
452 if (callbackImpl == nullptr) {
453 LOGE("Failed to get download callback");
454 return NError(JsErrCode::E_INNER_FAILED);
455 }
456 int32_t ret = callbackImpl->StopDownloadInner(downloadId, needClean);
457 if (ret != E_OK) {
458 ret = (ret == E_CLOUD_SDK) ? E_SERVICE_INNER_ERROR : ret;
459 return NError(Convert2JsErrNum(ret));
460 }
461 return NError(ERRNO_NOERR);
462 };
463
464 auto cbCompl = [](napi_env env, NError err) -> NVal {
465 if (err) {
466 return {env, err.GetNapiErr(env)};
467 }
468 return NVal::CreateUndefined(env);
469 };
470
471 string procedureName = "cloudFileCache";
472 auto asyncWork = GetPromiseOrCallBackWork(env, funcArg, maxArgSize);
473 return asyncWork == nullptr ? nullptr : asyncWork->Schedule(procedureName, cbExec, cbCompl).val_;
474 }
475
ParseEventFromParam(napi_env env,NFuncArg & funcArg)476 static std::tuple<int32_t, std::string> ParseEventFromParam(napi_env env, NFuncArg &funcArg)
477 {
478 auto [succProgress, progress, size] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
479 if (!succProgress || size == 0) {
480 LOGE("Parase event from parameter failed");
481 NError(EINVAL).ThrowErr(env);
482 return {EINVAL, ""};
483 }
484 string eventType(progress.get());
485 if (eventType == "multiProgress") {
486 eventType = MULTI_PROGRESS;
487 }
488 if ((eventType != PROGRESS && eventType != MULTI_PROGRESS)) {
489 LOGE("Invalid event type!");
490 return {EINVAL, ""};
491 }
492 return {E_OK, eventType};
493 }
494
On(napi_env env,napi_callback_info info)495 napi_value CloudFileCacheNapi::On(napi_env env, napi_callback_info info)
496 {
497 NFuncArg funcArg(env, info);
498 if (!funcArg.InitArgs(NARG_CNT::TWO)) {
499 LOGE("Batch-On Number of arguments unmatched");
500 NError(EINVAL).ThrowErr(env);
501 return nullptr;
502 }
503 auto [ret, eventType] = ParseEventFromParam(env, funcArg);
504 if (ret != E_OK) {
505 LOGE("On get event type failed!");
506 NError(ret).ThrowErr(env);
507 return nullptr;
508 }
509
510 if (!NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function)) {
511 LOGE("Batch-On argument type mismatch");
512 NError(EINVAL).ThrowErr(env);
513 return nullptr;
514 }
515
516 auto callbackImpl = GetCallbackImpl(env, funcArg, eventType, true);
517 if (callbackImpl == nullptr) {
518 LOGE("Failed to init callback");
519 NError(JsErrCode::E_INNER_FAILED).ThrowErr(env);
520 return nullptr;
521 }
522 auto status = callbackImpl->RegisterCallback(funcArg[NARG_POS::SECOND]);
523 if (status != napi_ok) {
524 LOGE("Failed to register callback, status: %{public}d", status);
525 NError(JsErrCode::E_INNER_FAILED).ThrowErr(env);
526 return nullptr;
527 }
528
529 return NVal::CreateUndefined(env).val_;
530 }
531
Off(napi_env env,napi_callback_info info)532 napi_value CloudFileCacheNapi::Off(napi_env env, napi_callback_info info)
533 {
534 NFuncArg funcArg(env, info);
535 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
536 LOGE("Off Number of arguments unmatched");
537 NError(EINVAL).ThrowErr(env);
538 return nullptr;
539 }
540 auto [ret, eventType] = ParseEventFromParam(env, funcArg);
541 if (ret != E_OK) {
542 LOGE("Off get event type failed!");
543 NError(ret).ThrowErr(env);
544 return nullptr;
545 }
546
547 napi_value callbackVel = nullptr;
548 if (funcArg.GetArgc() == (uint)NARG_CNT::TWO) {
549 if (!NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function)) {
550 LOGE("Off argument type mismatch");
551 NError(EINVAL).ThrowErr(env);
552 return nullptr;
553 }
554 callbackVel = funcArg[NARG_POS::SECOND];
555 }
556
557 auto callbackImpl = GetCallbackImpl(env, funcArg, eventType, false);
558 if (callbackImpl == nullptr || callbackImpl->UnregisterCallback(callbackVel) != napi_ok) {
559 LOGE("Failed to unregister callback, for eventType: %{public}s.", eventType.c_str());
560 NError(JsErrCode::E_INNER_FAILED).ThrowErr(env);
561 return nullptr;
562 }
563
564 return NVal::CreateUndefined(env).val_;
565 }
566
GetClassName()567 string CloudFileCacheNapi::GetClassName()
568 {
569 return className_;
570 }
571 } // namespace OHOS::FileManagement::CloudSync