• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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