1 /*
2  * Copyright (c) 2022 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 "common_want.h"
17 #include "common.h"
18 
19 #include "work_sched_errors.h"
20 #include "bool_wrapper.h"
21 #include "double_wrapper.h"
22 #include "int_wrapper.h"
23 #include "string_wrapper.h"
24 #include "want_params_wrapper.h"
25 #include "work_sched_hilog.h"
26 #include "napi/native_node_api.h"
27 #include "securec.h"
28 
29 namespace OHOS {
30 namespace WorkScheduler {
UnwrapStringFromJS(napi_env env,napi_value param,const std::string & defaultValue="")31 std::string UnwrapStringFromJS(napi_env env, napi_value param, const std::string &defaultValue = "")
32 {
33     size_t size = 0;
34     if (napi_get_value_string_utf8(env, param, nullptr, 0, &size) != napi_ok) {
35         return defaultValue;
36     }
37 
38     std::string value("");
39     if (size == 0) {
40         return defaultValue;
41     }
42 
43     char *buf = new (std::nothrow) char[size + 1];
44     if (buf == nullptr) {
45         return value;
46     }
47     (void)memset_s(buf, size + 1, 0, size + 1);
48 
49     bool rev = napi_get_value_string_utf8(env, param, buf, size + 1, &size) == napi_ok;
50     if (rev) {
51         value = buf;
52     } else {
53         value = defaultValue;
54     }
55 
56     delete[] buf;
57     buf = nullptr;
58     return value;
59 }
60 
InnerUnwrapJS(napi_env env,napi_value param,AAFwk::WantParams & wantParams,std::string strProName)61 bool InnerUnwrapJS(napi_env env, napi_value param, AAFwk::WantParams &wantParams, std::string strProName)
62 {
63     napi_valuetype jsValueType = napi_undefined;
64     napi_value jsProValue = nullptr;
65     napi_get_named_property(env, param, strProName.c_str(), &jsProValue);
66     napi_typeof(env, jsProValue, &jsValueType);
67     switch (jsValueType) {
68         case napi_string: {
69             std::string natValue = UnwrapStringFromJS(env, jsProValue, "");
70             wantParams.SetParam(strProName, AAFwk::String::Box(natValue));
71             break;
72         }
73         case napi_boolean: {
74             bool natValue = false;
75             napi_get_value_bool(env, jsProValue, &natValue);
76             wantParams.SetParam(strProName, AAFwk::Boolean::Box(natValue));
77             break;
78         }
79         case napi_number: {
80             int32_t natValue32 = 0;
81             double natValueDouble = 0.0;
82             bool isReadValue32 = false;
83             bool isReadDouble = false;
84             if (napi_get_value_int32(env, jsProValue, &natValue32) == napi_ok) {
85                 isReadValue32 = true;
86             }
87             if (napi_get_value_double(env, jsProValue, &natValueDouble) == napi_ok) {
88                 isReadDouble = true;
89             }
90             if (isReadValue32 && isReadDouble) {
91                 if (abs(natValueDouble - natValue32 * 1.0) > 0.0) {
92                     wantParams.SetParam(strProName, AAFwk::Double::Box(natValueDouble));
93                 } else {
94                     wantParams.SetParam(strProName, AAFwk::Integer::Box(natValue32));
95                 }
96             } else if (isReadValue32) {
97                 wantParams.SetParam(strProName, AAFwk::Integer::Box(natValue32));
98             } else if (isReadDouble) {
99                 wantParams.SetParam(strProName, AAFwk::Double::Box(natValueDouble));
100             }
101             break;
102         }
103         default: {
104             WS_HILOGE("Param %{public}s is illegal. The value is only supported basic type(Number, String, Boolean).",
105                 strProName.c_str());
106             Common::HandleParamErr(env, E_PARAMETERS_TYPE_ERR);
107             return false;
108         }
109     }
110     return true;
111 }
112 
UnwrapWantParams(napi_env env,napi_value param,AAFwk::WantParams & wantParams)113 bool UnwrapWantParams(napi_env env, napi_value param, AAFwk::WantParams &wantParams)
114 {
115     if (param == nullptr) {
116         return false;
117     }
118     napi_valuetype valueType = napi_undefined;
119     if (napi_typeof(env, param, &valueType) != napi_ok) {
120         return false;
121     }
122     if (valueType == napi_undefined) {
123         WS_HILOGI("parameters not set.");
124         return true;
125     } else if (valueType != napi_object) {
126         WS_HILOGE("parameters should be {[key: string]: value} format.");
127         Common::HandleParamErr(env, E_PARAMETERS_TYPE_ERR);
128         return false;
129     }
130 
131     napi_value jsProNameList = nullptr;
132     uint32_t jsProCount = 0;
133     napi_value jsProName = nullptr;
134     napi_get_property_names(env, param, &jsProNameList);
135     napi_get_array_length(env, jsProNameList, &jsProCount);
136     WS_HILOGI("Property size=%{public}d.", jsProCount);
137 
138     for (uint32_t index = 0; index < jsProCount; index++) {
139         napi_get_element(env, jsProNameList, index, &jsProName);
140         std::string strProName = UnwrapStringFromJS(env, jsProName, "");
141         WS_HILOGD("Property name=%{public}s.", strProName.c_str());
142         if (!InnerUnwrapJS(env, param, wantParams, strProName)) {
143             return false;
144         }
145     }
146     return true;
147 }
148 
InnerWrapWantParamsString(napi_env env,napi_value jsObject,const std::string & key,const AAFwk::WantParams & wantParams)149 bool InnerWrapWantParamsString(
150     napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams)
151 {
152     auto value = wantParams.GetParam(key);
153     AAFwk::IString *ao = AAFwk::IString::Query(value);
154     if (ao == nullptr) {
155         return false;
156     }
157 
158     std::string natValue = AAFwk::String::Unbox(ao);
159     napi_value jsValue;
160     napi_create_string_utf8(env, natValue.c_str(), NAPI_AUTO_LENGTH, &jsValue);
161     if (jsValue == nullptr) {
162         return false;
163     }
164 
165     NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false);
166     return true;
167 }
168 
InnerWrapWantParamsBool(napi_env env,napi_value jsObject,const std::string & key,const AAFwk::WantParams & wantParams)169 bool InnerWrapWantParamsBool(
170     napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams)
171 {
172     auto value = wantParams.GetParam(key);
173     AAFwk::IBoolean *bo = AAFwk::IBoolean::Query(value);
174     if (bo == nullptr) {
175         return false;
176     }
177 
178     bool natValue = AAFwk::Boolean::Unbox(bo);
179     napi_value jsValue;
180     napi_get_boolean(env, natValue, &jsValue);
181     if (jsValue == nullptr) {
182         return false;
183     }
184 
185     NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false);
186     return true;
187 }
188 
InnerWrapWantParamsInt(napi_env env,napi_value jsObject,const std::string & key,const AAFwk::WantParams & wantParams)189 bool InnerWrapWantParamsInt(
190     napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams)
191 {
192     auto value = wantParams.GetParam(key);
193     AAFwk::IInteger *ao = AAFwk::IInteger::Query(value);
194     if (ao == nullptr) {
195         return false;
196     }
197 
198     int natValue = AAFwk::Integer::Unbox(ao);
199     napi_value jsValue;
200     napi_create_int32(env, natValue, &jsValue);
201     if (jsValue == nullptr) {
202         return false;
203     }
204 
205     NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false);
206     return true;
207 }
208 
InnerWrapWantParamsDouble(napi_env env,napi_value jsObject,const std::string & key,const AAFwk::WantParams & wantParams)209 bool InnerWrapWantParamsDouble(
210     napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams)
211 {
212     auto value = wantParams.GetParam(key);
213     AAFwk::IDouble *ao = AAFwk::IDouble::Query(value);
214     if (ao == nullptr) {
215         return false;
216     }
217 
218     double natValue = AAFwk::Double::Unbox(ao);
219     napi_value jsValue;
220     napi_create_double(env, natValue, &jsValue);
221     if (jsValue == nullptr) {
222         return false;
223     }
224 
225     NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false);
226     return true;
227 }
228 
WrapWantParams(napi_env env,const AAFwk::WantParams & wantParams)229 napi_value WrapWantParams(napi_env env, const AAFwk::WantParams &wantParams)
230 {
231     WS_HILOGD("Start wrap wantParams.");
232     napi_value jsObject = nullptr;
233     NAPI_CALL(env, napi_create_object(env, &jsObject));
234 
235     const std::map<std::string, sptr<AAFwk::IInterface>> paramList = wantParams.GetParams();
236     for (auto iter = paramList.begin(); iter != paramList.end(); iter++) {
237         if (AAFwk::IString::Query(iter->second) != nullptr) {
238             InnerWrapWantParamsString(env, jsObject, iter->first, wantParams);
239         } else if (AAFwk::IBoolean::Query(iter->second) != nullptr) {
240             InnerWrapWantParamsBool(env, jsObject, iter->first, wantParams);
241         } else if (AAFwk::IInteger::Query(iter->second) != nullptr) {
242             InnerWrapWantParamsInt(env, jsObject, iter->first, wantParams);
243         } else if (AAFwk::IDouble::Query(iter->second) != nullptr) {
244             InnerWrapWantParamsDouble(env, jsObject, iter->first, wantParams);
245         }
246     }
247     return jsObject;
248 }
249 }  // namespace WorkScheduler
250 }  // namespace OHOS
251