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 "js_api_utils.h"
17
18 #include <climits>
19 #include <vector>
20
21 #include "ability_business_error.h"
22 #include "array_wrapper.h"
23 #include "bool_wrapper.h"
24 #include "double_wrapper.h"
25 #include "hilog_wrapper.h"
26 #include "int_wrapper.h"
27 #include "ipc_skeleton.h"
28 #include "js_error_utils.h"
29 #include "napi_remote_object.h"
30 #include "remote_object_wrapper.h"
31 #include "string_wrapper.h"
32 #include "tokenid_kit.h"
33 #include "want_params_wrapper.h"
34
35 namespace OHOS {
36 namespace AbilityRuntime {
37 namespace JsApiUtils {
UnWrapAbilityResult(NativeEngine & engine,NativeValue * argv,int & resultCode,AAFwk::Want & want)38 bool UnWrapAbilityResult(NativeEngine &engine, NativeValue* argv, int &resultCode, AAFwk::Want &want)
39 {
40 if (!IsNarmalObject(argv)) {
41 HILOG_WARN("invalid argv");
42 return false;
43 }
44
45 NativeObject* jObj = ConvertNativeValueTo<NativeObject>(argv);
46 if (!UnwrapNumberValue(jObj->GetProperty("resultCode"), resultCode)) {
47 HILOG_WARN("resultCode invalid");
48 return false;
49 }
50
51 return UnWrapWant(engine, jObj->GetProperty("want"), want);
52 }
53
UnWrapWant(NativeEngine & engine,NativeValue * param,AAFwk::Want & want)54 bool UnWrapWant(NativeEngine &engine, NativeValue* param, AAFwk::Want &want)
55 {
56 if (!IsNarmalObject(param)) {
57 HILOG_WARN("param is invalid.");
58 return false;
59 }
60
61 NativeObject* wantObj = ConvertNativeValueTo<NativeObject>(param);
62 AAFwk::WantParams wantParams;
63 if (UnwrapWantParams(engine, wantObj->GetProperty("parameters"), wantParams)) {
64 want.SetParams(wantParams);
65 }
66
67 std::string natValueString;
68 if (UnwrapStringValue(wantObj->GetProperty("action"), natValueString)) {
69 want.SetAction(natValueString);
70 }
71
72 std::vector<std::string> natValueStringList;
73 if (UnwrapArrayStringValue(wantObj->GetProperty("entities"), natValueStringList)) {
74 for (size_t i = 0; i < natValueStringList.size(); i++) {
75 want.AddEntity(natValueStringList[i]);
76 }
77 }
78
79 natValueString.clear();
80 if (UnwrapStringValue(wantObj->GetProperty("uri"), natValueString)) {
81 want.SetUri(natValueString);
82 }
83
84 int32_t flags = 0;
85 if (UnwrapNumberValue(wantObj->GetProperty("flags"), flags)) {
86 want.SetFlags(flags);
87 }
88
89 std::string deviceId, bundleName, abilityName, moduleName;
90 UnwrapStringValue(wantObj->GetProperty("deviceId"), deviceId);
91 UnwrapStringValue(wantObj->GetProperty("bundleName"), bundleName);
92 UnwrapStringValue(wantObj->GetProperty("abilityName"), abilityName);
93 UnwrapStringValue(wantObj->GetProperty("moduleName"), moduleName);
94 want.SetElementName(deviceId, bundleName, abilityName, moduleName);
95
96 natValueString.clear();
97 if (UnwrapStringValue(wantObj->GetProperty("type"), natValueString)) {
98 want.SetType(natValueString);
99 }
100
101 return true;
102 }
103 namespace {
BlackListFilter(const std::string & strProName)104 bool BlackListFilter(const std::string &strProName)
105 {
106 if (strProName == AAFwk::Want::PARAM_RESV_WINDOW_MODE) {
107 return true;
108 }
109 if (strProName == AAFwk::Want::PARAM_RESV_DISPLAY_ID) {
110 return true;
111 }
112 return false;
113 }
114
UnwrapFdObject(const std::string & propName,NativeValue * jsProp,AAFwk::WantParams & wantParams)115 bool UnwrapFdObject(const std::string &propName, NativeValue* jsProp, AAFwk::WantParams &wantParams)
116 {
117 NativeObject* propObj = ConvertNativeValueTo<NativeObject>(jsProp);
118 if (propObj == nullptr) {
119 return false;
120 }
121 std::string strType;
122 if (!UnwrapStringValue(propObj->GetProperty(AAFwk::TYPE_PROPERTY), strType) ||
123 strType != AAFwk::FD) {
124 return false;
125 }
126
127 int32_t nativeFd = 0;
128 if (UnwrapNumberValue(propObj->GetProperty(AAFwk::VALUE_PROPERTY), nativeFd)) {
129 AAFwk::WantParams wp;
130 wp.SetParam(AAFwk::TYPE_PROPERTY, AAFwk::String::Box(AAFwk::FD));
131 wp.SetParam(AAFwk::VALUE_PROPERTY, AAFwk::Integer::Box(nativeFd));
132 sptr<AAFwk::IWantParams> pWantParams = AAFwk::WantParamWrapper::Box(wp);
133 wantParams.SetParam(propName, pWantParams);
134 } else {
135 HILOG_INFO("parse FD failed.");
136 }
137 return true;
138 }
139
UnwrapRemoteObject(NativeEngine & engine,const std::string & propName,NativeValue * jsProp,AAFwk::WantParams & wantParams)140 bool UnwrapRemoteObject(NativeEngine &engine, const std::string &propName,
141 NativeValue* jsProp, AAFwk::WantParams &wantParams)
142 {
143 // This is used inner, so no nullptr check
144 NativeObject* propObj = ConvertNativeValueTo<NativeObject>(jsProp);
145 if (propObj == nullptr) {
146 return false;
147 }
148 std::string strType;
149 if (!UnwrapStringValue(propObj->GetProperty(AAFwk::TYPE_PROPERTY), strType) ||
150 strType != AAFwk::REMOTE_OBJECT) {
151 return false;
152 }
153
154 auto selfToken = IPCSkeleton::GetSelfTokenID();
155 if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) {
156 HILOG_WARN("not system app, REMOTE_OBJECT is FORIBBED IN WANT.");
157 return true;
158 }
159
160 sptr<IRemoteObject> remoteObject = NAPI_ohos_rpc_getNativeRemoteObject(reinterpret_cast<napi_env>(&engine),
161 reinterpret_cast<napi_value>(propObj->GetProperty(AAFwk::VALUE_PROPERTY)));
162 if (!remoteObject) {
163 HILOG_WARN("failed to transfer to remoteObject");
164 return true;
165 }
166
167 AAFwk::WantParams wp;
168 wp.SetParam(AAFwk::TYPE_PROPERTY, AAFwk::String::Box(AAFwk::REMOTE_OBJECT));
169 wp.SetParam(AAFwk::VALUE_PROPERTY, AAFwk::RemoteObjectWrap::Box(remoteObject));
170 sptr<AAFwk::IWantParams> pWantParams = AAFwk::WantParamWrapper::Box(wp);
171 wantParams.SetParam(propName, pWantParams);
172 return true;
173 }
174
UnwrapStringArrayParams(const std::string & propName,NativeArray * array,AAFwk::WantParams & wantParams,size_t size)175 void UnwrapStringArrayParams(const std::string &propName, NativeArray* array,
176 AAFwk::WantParams &wantParams, size_t size)
177 {
178 std::vector<sptr<AAFwk::IString>> tempResult;
179 tempResult.reserve(size);
180 for (size_t i = 0; i < size; i++) {
181 std::string value;
182 if (UnwrapStringValue(array->GetElement(i), value)) {
183 tempResult.push_back(AAFwk::String::Box(value));
184 }
185 }
186 sptr<AAFwk::IArray> arrayProp = new AAFwk::Array(tempResult.size(), AAFwk::g_IID_IString);
187 for (size_t i = 0; i < tempResult.size(); i++) {
188 arrayProp->Set(i, tempResult[i]);
189 }
190 wantParams.SetParam(propName, arrayProp);
191 }
192
UnwrapNumberArrayParams(const std::string & propName,NativeArray * array,AAFwk::WantParams & wantParams,size_t size)193 void UnwrapNumberArrayParams(const std::string &propName, NativeArray* array,
194 AAFwk::WantParams &wantParams, size_t size)
195 {
196 std::vector<sptr<AAFwk::IDouble>> tempResult;
197 tempResult.reserve(size);
198 for (size_t i = 0; i < size; i++) {
199 double value;
200 if (UnwrapNumberValue(array->GetElement(i), value)) {
201 tempResult.push_back(AAFwk::Double::Box(value));
202 }
203 }
204 sptr<AAFwk::IArray> arrayProp = new AAFwk::Array(tempResult.size(), AAFwk::g_IID_IDouble);
205 for (size_t i = 0; i < tempResult.size(); i++) {
206 arrayProp->Set(i, tempResult[i]);
207 }
208 wantParams.SetParam(propName, arrayProp);
209 }
210
UnwrapBoolArrayParams(const std::string & propName,NativeArray * array,AAFwk::WantParams & wantParams,size_t size)211 void UnwrapBoolArrayParams(const std::string &propName, NativeArray* array,
212 AAFwk::WantParams &wantParams, size_t size)
213 {
214 std::vector<sptr<AAFwk::IBoolean>> tempResult;
215 tempResult.reserve(size);
216 for (size_t i = 0; i < size; i++) {
217 auto element = array->GetElement(i);
218 if (element && element->TypeOf() == NATIVE_BOOLEAN) {
219 tempResult.push_back(AAFwk::Boolean::Box(bool(*ConvertNativeValueTo<NativeBoolean>(element))));
220 }
221 }
222 sptr<AAFwk::IArray> arrayProp = new AAFwk::Array(tempResult.size(), AAFwk::g_IID_IBoolean);
223 for (size_t i = 0; i < tempResult.size(); i++) {
224 arrayProp->Set(i, tempResult[i]);
225 }
226 wantParams.SetParam(propName, arrayProp);
227 }
228
UnwrapObjectArrayParams(NativeEngine & engine,const std::string & propName,NativeArray * array,AAFwk::WantParams & wantParams,size_t size)229 void UnwrapObjectArrayParams(NativeEngine &engine, const std::string &propName, NativeArray* array,
230 AAFwk::WantParams &wantParams, size_t size)
231 {
232 std::vector<sptr<AAFwk::IWantParams>> tempResult;
233 tempResult.reserve(size);
234 for (size_t i = 0; i < size; i++) {
235 AAFwk::WantParams value;
236 if (UnwrapWantParams(engine, array->GetElement(i), value)) {
237 value.DumpInfo(0);
238 tempResult.push_back(AAFwk::WantParamWrapper::Box(value));
239 }
240 }
241 sptr<AAFwk::IArray> arrayProp = new AAFwk::Array(tempResult.size(), AAFwk::g_IID_IWantParams);
242 for (size_t i = 0; i < tempResult.size(); i++) {
243 arrayProp->Set(i, tempResult[i]);
244 }
245 wantParams.SetParam(propName, arrayProp);
246 }
247
UnwrapArrayParams(NativeEngine & engine,const std::string & propName,NativeValue * jsProp,AAFwk::WantParams & wantParams)248 bool UnwrapArrayParams(NativeEngine &engine, const std::string &propName,
249 NativeValue* jsProp, AAFwk::WantParams &wantParams)
250 {
251 // This is used inner, so no nullptr check
252 if (!jsProp->IsArray()) {
253 return false;
254 }
255 // There should be only one type in the array.
256 auto nativeArray = ConvertNativeValueTo<NativeArray>(jsProp);
257 auto arrayLen = nativeArray->GetLength();
258 if (arrayLen == 0) {
259 return true;
260 }
261
262 auto firstElemnt = nativeArray->GetElement(0);
263 switch (firstElemnt->TypeOf()) {
264 case NATIVE_STRING: {
265 UnwrapStringArrayParams(propName, nativeArray, wantParams, arrayLen);
266 break;
267 }
268 case NATIVE_NUMBER: {
269 UnwrapNumberArrayParams(propName, nativeArray, wantParams, arrayLen);
270 break;
271 }
272 case NATIVE_BOOLEAN: {
273 UnwrapBoolArrayParams(propName, nativeArray, wantParams, arrayLen);
274 break;
275 }
276 case NATIVE_OBJECT: {
277 UnwrapObjectArrayParams(engine, propName, nativeArray, wantParams, arrayLen);
278 break;
279 }
280 default: {
281 HILOG_WARN("Unsupported prop: %{public}s, %{public}d", propName.c_str(), jsProp->TypeOf());
282 break;
283 }
284 }
285
286 return true;
287 }
288
UnwrapObjPropForWantParams(NativeEngine & engine,const std::string & propName,NativeValue * jsProp,AAFwk::WantParams & wantParams)289 void UnwrapObjPropForWantParams(NativeEngine &engine, const std::string &propName,
290 NativeValue* jsProp, AAFwk::WantParams &wantParams)
291 {
292 if (UnwrapFdObject(propName, jsProp, wantParams)) {
293 return;
294 }
295
296 if (UnwrapRemoteObject(engine, propName, jsProp, wantParams)) {
297 return;
298 }
299
300 if (UnwrapArrayParams(engine, propName, jsProp, wantParams)) {
301 return;
302 }
303
304 AAFwk::WantParams wp;
305 if (UnwrapWantParams(engine, jsProp, wp)) {
306 wantParams.SetParam(propName, AAFwk::WantParamWrapper::Box(wp));
307 }
308 }
309 }
310
UnwrapWantParams(NativeEngine & engine,NativeValue * param,AAFwk::WantParams & wantParams)311 bool UnwrapWantParams(NativeEngine &engine, NativeValue* param, AAFwk::WantParams &wantParams)
312 {
313 if (!IsNarmalObject(param)) {
314 HILOG_INFO("param is invalid.");
315 return false;
316 }
317
318 NativeObject* paramObj = ConvertNativeValueTo<NativeObject>(param);
319 std::vector<std::string> propNames;
320 if (!UnwrapArrayStringValue(paramObj->GetPropertyNames(), propNames)) {
321 HILOG_WARN("Get prop names failed.");
322 return false;
323 }
324
325 for (const auto &propName : propNames) {
326 if (BlackListFilter(propName)) {
327 HILOG_INFO("%{public}s is filtered.", propName.c_str());
328 continue;
329 }
330 auto jsProp = paramObj->GetProperty(propName.c_str());
331 if (!jsProp) {
332 HILOG_WARN("Prop is invalid: %{public}s", propName.c_str());
333 continue;
334 }
335 switch (jsProp->TypeOf()) {
336 case NATIVE_STRING: {
337 std::string value;
338 UnwrapStringValue(jsProp, value);
339 wantParams.SetParam(propName, AAFwk::String::Box(value));
340 break;
341 }
342 case NATIVE_BOOLEAN: {
343 bool value = *ConvertNativeValueTo<NativeBoolean>(jsProp);
344 wantParams.SetParam(propName, AAFwk::Boolean::Box(value));
345 break;
346 }
347 case NATIVE_NUMBER: {
348 // In js, all is double and the user should make a desision.
349 double value = *ConvertNativeValueTo<NativeNumber>(jsProp);
350 wantParams.SetParam(propName, AAFwk::Double::Box(value));
351 break;
352 }
353 case NATIVE_OBJECT: {
354 UnwrapObjPropForWantParams(engine, propName, jsProp, wantParams);
355 break;
356 }
357 default: {
358 HILOG_WARN("Unsupported prop: %{public}s, %{public}d", propName.c_str(), jsProp->TypeOf());
359 break;
360 }
361 };
362 }
363
364 return true;
365 }
366
UnwrapStringValue(NativeValue * param,std::string & value)367 bool UnwrapStringValue(NativeValue* param, std::string &value)
368 {
369 if (param == nullptr) {
370 HILOG_INFO("param is nullptr!");
371 return false;
372 }
373 if (param->TypeOf() != NativeValueType::NATIVE_STRING) {
374 HILOG_INFO("invalid type!");
375 return false;
376 }
377
378 auto nativeString = ConvertNativeValueTo<NativeString>(param);
379 size_t size = 0;
380 nativeString->GetCString(nullptr, 0, &size);
381 if (size == 0 || size >= INT_MAX) {
382 HILOG_INFO("string size abnormal: %{public}zu", size);
383 return true;
384 }
385
386 value.resize(size + 1);
387 nativeString->GetCString(value.data(), size + 1, &size);
388 value.pop_back();
389
390 return true;
391 }
392
UnwrapArrayStringValue(NativeValue * param,std::vector<std::string> & value)393 bool UnwrapArrayStringValue(NativeValue* param, std::vector<std::string> &value)
394 {
395 if (param == nullptr) {
396 HILOG_INFO("param is nullptr!");
397 return false;
398 }
399 if (!param->IsArray()) {
400 HILOG_INFO("invalid type!");
401 return false;
402 }
403
404 auto nativeArray = ConvertNativeValueTo<NativeArray>(param);
405 auto arrayLen = nativeArray->GetLength();
406 if (arrayLen == 0) {
407 return true;
408 }
409
410 value.reserve(arrayLen);
411 for (uint32_t i = 0; i < arrayLen; i++) {
412 std::string strItem;
413 if (UnwrapStringValue(nativeArray->GetElement(i), strItem)) {
414 value.emplace_back(std::move(strItem));
415 }
416 }
417 return true;
418 }
419
IsNarmalObject(NativeValue * value)420 bool IsNarmalObject(NativeValue* value)
421 {
422 if (value == nullptr) {
423 HILOG_DEBUG("value is nullptr!");
424 return false;
425 }
426 if (value->TypeOf() == NativeValueType::NATIVE_UNDEFINED) {
427 HILOG_DEBUG("value is undefined!");
428 return false;
429 }
430 if (value->TypeOf() != NativeValueType::NATIVE_OBJECT) {
431 HILOG_DEBUG("invalid type of value!");
432 return false;
433 }
434 return true;
435 }
436 }
437 } // namespace AbilityRuntime
438 } // namespace OHOS
439
440