• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #define LOG_TAG "GetDataParamsNapi"
17 #include "get_data_params_napi.h"
18 
19 #include "logger.h"
20 #include "napi_data_utils.h"
21 #include "unified_data_napi.h"
22 
23 namespace OHOS {
24 namespace UDMF {
25 static constexpr int32_t PROGRESS_INIT = 0;
26 static constexpr int32_t PROGRESS_ALL_FINISHED = 100;
27 ConcurrentMap<std::string, napi_threadsafe_function> GetDataParamsNapi::tsfns;
28 
Convert2NativeValue(napi_env env,napi_value in,GetDataParams & getDataParams,const std::string & key)29 bool GetDataParamsNapi::Convert2NativeValue(napi_env env, napi_value in,
30     GetDataParams &getDataParams, const std::string &key)
31 {
32     LOG_DEBUG(UDMF_KITS_NAPI, "Start.");
33 
34     napi_value jsProgressIndicator = nullptr;
35     NAPI_CALL_BASE(env, napi_get_named_property(env, in, "progressIndicator", &jsProgressIndicator), false);
36     int32_t progressIndicator = static_cast<int32_t>(ProgressIndicator::NONE);
37     NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsProgressIndicator, progressIndicator), false);
38     getDataParams.progressIndicator = static_cast<ProgressIndicator>(progressIndicator);
39 
40     napi_value JsListener = nullptr;
41     NAPI_CALL_BASE(env, napi_get_named_property(env, in, "dataProgressListener", &JsListener), false);
42     napi_valuetype valueType = napi_undefined;
43     NAPI_CALL_BASE(env, napi_typeof(env, JsListener, &valueType), false);
44     NAPI_ASSERT_BASE(env, valueType == napi_function, "progressListener type must be DataProgressListener", false);
45     if (!SetProgressListener(env, getDataParams, JsListener, key)) {
46         LOG_ERROR(UDMF_KITS_NAPI, "SetProgressListener failed.");
47         return false;
48     }
49 
50     bool hasDestUri = false;
51     NAPI_CALL_BASE(env, napi_has_named_property(env, in, "destUri", &hasDestUri), false);
52     if (hasDestUri) {
53         napi_value jsDestUri = nullptr;
54         NAPI_CALL_BASE(env, napi_get_named_property(env, in, "destUri", &jsDestUri), false);
55         NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsDestUri, getDataParams.destUri), false);
56     }
57 
58     bool hasFileConflictOptions = false;
59     NAPI_CALL_BASE(env, napi_has_named_property(env, in, "fileConflictOptions", &hasFileConflictOptions), false);
60     if (hasFileConflictOptions) {
61         napi_value jsFileConflictOptions = nullptr;
62         NAPI_CALL_BASE(env, napi_get_named_property(env, in, "fileConflictOptions", &jsFileConflictOptions), false);
63         int32_t fileConflictOptions = static_cast<int32_t>(FileConflictOptions::OVERWRITE);
64         NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsFileConflictOptions, fileConflictOptions), false);
65         getDataParams.fileConflictOptions = static_cast<FileConflictOptions>(fileConflictOptions);
66     }
67 
68     return true;
69 }
70 
SetProgressListener(napi_env env,GetDataParams & getDataParams,napi_value callback,const std::string & key)71 bool GetDataParamsNapi::SetProgressListener(napi_env env, GetDataParams &getDataParams,
72     napi_value callback, const std::string &key)
73 {
74     LOG_DEBUG(UDMF_KITS_NAPI, "Start.");
75     tsfns.Compute(key, [&](const std::string &key, napi_threadsafe_function &tsfn) {
76         if (tsfn != nullptr) {
77             LOG_WARN(UDMF_KITS_NAPI, "Listener has existed!");
78             napi_release_threadsafe_function(tsfn, napi_tsfn_release);
79             tsfn = nullptr;
80         }
81         napi_value workName;
82         napi_create_string_utf8(env, "threadsafe_function", NAPI_AUTO_LENGTH, &workName);
83         auto status = napi_create_threadsafe_function(env, callback, nullptr, workName, 0, 1, nullptr,
84             nullptr, nullptr, CallProgressListener, &tsfn);
85         if (status != napi_ok) {
86             LOG_ERROR(UDMF_KITS_NAPI, "napi_create_threadsafe_function failed, status=%{public}d", status);
87             return false;
88         }
89         return true;
90     });
91 
92     getDataParams.progressListener = [key](ProgressInfo progressInfo, std::shared_ptr<UnifiedData> data) {
93         bool listenerExist = tsfns.ComputeIfPresent(key, [&](const std::string &key, napi_threadsafe_function &tsfn) {
94             auto listenerArgs = CreateListenerArgs(progressInfo, data);
95             if (listenerArgs == nullptr) {
96                 return false;
97             }
98             auto status = napi_call_threadsafe_function(tsfn, listenerArgs, napi_tsfn_blocking);
99             if (status != napi_ok) {
100                 LOG_ERROR(UDMF_KITS_NAPI, "napi_call_threadsafe_function failed, status=%{public}d", status);
101                 return false;
102             }
103             if (progressInfo.progress >= PROGRESS_ALL_FINISHED ||
104                 progressInfo.progress < PROGRESS_INIT) {
105                 napi_release_threadsafe_function(tsfn, napi_tsfn_release);
106                 return false;
107             }
108             return true;
109         });
110         if (!listenerExist) {
111             LOG_INFO(UDMF_KITS_NAPI, "No listener exist.");
112         }
113     };
114     return true;
115 }
116 
CallProgressListener(napi_env env,napi_value callback,void * context,void * data)117 void GetDataParamsNapi::CallProgressListener(napi_env env, napi_value callback, void *context, void *data)
118 {
119     ListenerArgs* listenerArgs = static_cast<ListenerArgs*>(data);
120     napi_value param[ListenerArgs::ARGV_SIZE];
121 
122     NapiDataUtils::SetValue(env, listenerArgs->progressInfo, param[0]);
123 
124     if (listenerArgs->unifiedData == nullptr) {
125         NapiDataUtils::SetValue(env, nullptr, param[1]);
126     } else {
127         std::shared_ptr<UnifiedData> unifiedData = std::make_shared<UnifiedData>();
128         unifiedData->SetRecords(listenerArgs->unifiedData->GetRecords());
129         UnifiedDataNapi::NewInstance(env, unifiedData, param[1]);
130     }
131 
132     auto status = napi_call_function(env, nullptr, callback, ListenerArgs::ARGV_SIZE, param, nullptr);
133     if (status != napi_ok) {
134         LOG_ERROR(UDMF_KITS_NAPI, "napi_call_function failed, status=%{public}d", status);
135     }
136 
137     DeleteListenerArgs(listenerArgs);
138 }
139 
CreateListenerArgs(ProgressInfo progressInfo,std::shared_ptr<UnifiedData> data)140 GetDataParamsNapi::ListenerArgs* GetDataParamsNapi::CreateListenerArgs(
141     ProgressInfo progressInfo, std::shared_ptr<UnifiedData> data)
142 {
143     auto listenerArgs = new (std::nothrow) ListenerArgs;
144     if (listenerArgs == nullptr) {
145         LOG_ERROR(UDMF_KITS_NAPI, "No memory for listenerArgs malloc");
146         return nullptr;
147     }
148     listenerArgs->progressInfo = progressInfo;
149     listenerArgs->unifiedData = nullptr;
150     if (data != nullptr) {
151         listenerArgs->unifiedData = new (std::nothrow) UnifiedData;
152         if (listenerArgs->unifiedData == nullptr) {
153             LOG_ERROR(UDMF_KITS_NAPI, "No memory for unifiedData malloc");
154             delete listenerArgs;
155             return nullptr;
156         }
157         listenerArgs->unifiedData->SetRecords(data->GetRecords());
158     }
159     return listenerArgs;
160 }
161 
DeleteListenerArgs(ListenerArgs * listenerArgs)162 void GetDataParamsNapi::DeleteListenerArgs(ListenerArgs *listenerArgs)
163 {
164     if (listenerArgs->unifiedData != nullptr) {
165         delete listenerArgs->unifiedData;
166         listenerArgs->unifiedData = nullptr;
167     }
168     delete listenerArgs;
169     listenerArgs = nullptr;
170 }
171 
172 } // namespace UDMF
173 } // namespace OHOS