• 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     bool hasAcceptableInfo = false;
69     NAPI_CALL_BASE(env, napi_has_named_property(env, in, "acceptableInfo", &hasAcceptableInfo), false);
70     if (hasAcceptableInfo) {
71         napi_value jsDataLoadInfo = nullptr;
72         NAPI_CALL_BASE(env, napi_get_named_property(env, in, "acceptableInfo", &jsDataLoadInfo), false);
73         NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsDataLoadInfo, getDataParams.acceptableInfo), false);
74     }
75     return true;
76 }
77 
SetProgressListener(napi_env env,GetDataParams & getDataParams,napi_value callback,const std::string & key)78 bool GetDataParamsNapi::SetProgressListener(napi_env env, GetDataParams &getDataParams,
79     napi_value callback, const std::string &key)
80 {
81     LOG_DEBUG(UDMF_KITS_NAPI, "Start.");
82     tsfns.Compute(key, [&](const std::string &key, napi_threadsafe_function &tsfn) {
83         if (tsfn != nullptr) {
84             LOG_WARN(UDMF_KITS_NAPI, "Listener has existed!");
85             napi_release_threadsafe_function(tsfn, napi_tsfn_release);
86             tsfn = nullptr;
87         }
88         napi_value workName;
89         napi_create_string_utf8(env, "threadsafe_function", NAPI_AUTO_LENGTH, &workName);
90         auto status = napi_create_threadsafe_function(env, callback, nullptr, workName, 0, 1, nullptr,
91             nullptr, nullptr, CallProgressListener, &tsfn);
92         if (status != napi_ok) {
93             LOG_ERROR(UDMF_KITS_NAPI, "napi_create_threadsafe_function failed, status=%{public}d", status);
94             return false;
95         }
96         return true;
97     });
98 
99     getDataParams.progressListener = [key](ProgressInfo progressInfo, std::shared_ptr<UnifiedData> data) {
100         bool listenerExist = tsfns.ComputeIfPresent(key, [&](const std::string &key, napi_threadsafe_function &tsfn) {
101             auto listenerArgs = CreateListenerArgs(progressInfo, data);
102             if (listenerArgs == nullptr) {
103                 return false;
104             }
105             auto status = napi_call_threadsafe_function(tsfn, listenerArgs, napi_tsfn_blocking);
106             if (status != napi_ok) {
107                 LOG_ERROR(UDMF_KITS_NAPI, "napi_call_threadsafe_function failed, status=%{public}d", status);
108                 return false;
109             }
110             if (progressInfo.progress >= PROGRESS_ALL_FINISHED ||
111                 progressInfo.progress < PROGRESS_INIT) {
112                 napi_release_threadsafe_function(tsfn, napi_tsfn_release);
113                 return false;
114             }
115             return true;
116         });
117         if (!listenerExist) {
118             LOG_INFO(UDMF_KITS_NAPI, "No listener exist.");
119         }
120     };
121     return true;
122 }
123 
CallProgressListener(napi_env env,napi_value callback,void * context,void * data)124 void GetDataParamsNapi::CallProgressListener(napi_env env, napi_value callback, void *context, void *data)
125 {
126     ListenerArgs* listenerArgs = static_cast<ListenerArgs*>(data);
127     napi_value param[ListenerArgs::ARGV_SIZE];
128 
129     NapiDataUtils::SetValue(env, listenerArgs->progressInfo, param[0]);
130 
131     if (listenerArgs->unifiedData == nullptr) {
132         NapiDataUtils::SetValue(env, nullptr, param[1]);
133     } else {
134         std::shared_ptr<UnifiedData> unifiedData = std::make_shared<UnifiedData>();
135         unifiedData->SetRecords(listenerArgs->unifiedData->GetRecords());
136         UnifiedDataNapi::NewInstance(env, unifiedData, param[1]);
137     }
138 
139     auto status = napi_call_function(env, nullptr, callback, ListenerArgs::ARGV_SIZE, param, nullptr);
140     if (status != napi_ok) {
141         LOG_ERROR(UDMF_KITS_NAPI, "napi_call_function failed, status=%{public}d", status);
142     }
143 
144     DeleteListenerArgs(listenerArgs);
145 }
146 
CreateListenerArgs(ProgressInfo progressInfo,std::shared_ptr<UnifiedData> data)147 GetDataParamsNapi::ListenerArgs* GetDataParamsNapi::CreateListenerArgs(
148     ProgressInfo progressInfo, std::shared_ptr<UnifiedData> data)
149 {
150     auto listenerArgs = new (std::nothrow) ListenerArgs;
151     if (listenerArgs == nullptr) {
152         LOG_ERROR(UDMF_KITS_NAPI, "No memory for listenerArgs malloc");
153         return nullptr;
154     }
155     listenerArgs->progressInfo = progressInfo;
156     listenerArgs->unifiedData = nullptr;
157     if (data != nullptr) {
158         listenerArgs->unifiedData = new (std::nothrow) UnifiedData;
159         if (listenerArgs->unifiedData == nullptr) {
160             LOG_ERROR(UDMF_KITS_NAPI, "No memory for unifiedData malloc");
161             delete listenerArgs;
162             return nullptr;
163         }
164         listenerArgs->unifiedData->SetRecords(data->GetRecords());
165     }
166     return listenerArgs;
167 }
168 
DeleteListenerArgs(ListenerArgs * listenerArgs)169 void GetDataParamsNapi::DeleteListenerArgs(ListenerArgs *listenerArgs)
170 {
171     if (listenerArgs->unifiedData != nullptr) {
172         delete listenerArgs->unifiedData;
173         listenerArgs->unifiedData = nullptr;
174     }
175     delete listenerArgs;
176     listenerArgs = nullptr;
177 }
178 
179 } // namespace UDMF
180 } // namespace OHOS