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 #include "ani_common_want.h"
17 #include "ani_common_util.h"
18 #include "array_wrapper.h"
19 #include "bool_wrapper.h"
20 #include "byte_wrapper.h"
21 #include "double_wrapper.h"
22 #include "float_wrapper.h"
23 #include "hilog_tag_wrapper.h"
24 #include "int_wrapper.h"
25 #include "ipc_skeleton.h"
26 #include "js_runtime_utils.h"
27 #include "long_wrapper.h"
28 #include "napi_remote_object.h"
29 #include "remote_object_wrapper.h"
30 #include "short_wrapper.h"
31 #include "string_wrapper.h"
32 #include "tokenid_kit.h"
33 #include "want_params_wrapper.h"
34 #include "zchar_wrapper.h"
35
36 namespace OHOS {
37 namespace AppExecFwk {
38 using namespace OHOS::AbilityRuntime;
39 namespace {
40 constexpr const char* ABILITY_WANT_CLASS_NAME = "L@ohos/app/ability/Want/Want;";
41 constexpr const char* TOOL_CLASS_NAME = "L@ohos/app/ability/Want/RecordSerializeTool;";
42 constexpr const char* INNER_CLASS_NAME = "Lability/abilityResult/AbilityResultInner;";
43 constexpr const char* ELEMENTNAME_CLASS_NAME = "LbundleManager/ElementNameInner/ElementNameInner;";
44
InnerWrapWantParams(ani_env * env,ani_class wantCls,ani_object wantObject,const AAFwk::WantParams & wantParams)45 bool InnerWrapWantParams(ani_env* env, ani_class wantCls, ani_object wantObject, const AAFwk::WantParams& wantParams)
46 {
47 ani_ref wantParamRef = WrapWantParams(env, wantParams);
48 if (wantParamRef == nullptr) {
49 TAG_LOGE(AAFwkTag::ANI, "failed to WrapWantParams");
50 return false;
51 }
52 return SetFieldRefByName(env, wantCls, wantObject, "parameters", wantParamRef);
53 }
54
InnerUnwrapWantParams(ani_env * env,ani_object wantObject,AAFwk::WantParams & wantParams)55 bool InnerUnwrapWantParams(ani_env* env, ani_object wantObject, AAFwk::WantParams& wantParams)
56 {
57 ani_ref wantParamRef = nullptr;
58 if (!GetFieldRefByName(env, wantObject, "parameters", wantParamRef)) {
59 TAG_LOGE(AAFwkTag::ANI, "failed to get want parameter");
60 return false;
61 }
62 return UnwrapWantParams(env, wantParamRef, wantParams);
63 }
64 }
65
WrapWant(ani_env * env,const AAFwk::Want & want)66 ani_object WrapWant(ani_env *env, const AAFwk::Want &want)
67 {
68 TAG_LOGD(AAFwkTag::ANI, "WrapWant called");
69 if (env == nullptr) {
70 TAG_LOGE(AAFwkTag::ANI, "null env");
71 return nullptr;
72 }
73 ani_class cls = nullptr;
74 ani_status status = ANI_ERROR;
75 ani_method method = nullptr;
76 ani_object object = nullptr;
77 if ((status = env->FindClass(ABILITY_WANT_CLASS_NAME, &cls)) != ANI_OK) {
78 TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
79 return nullptr;
80 }
81 if (cls == nullptr) {
82 TAG_LOGE(AAFwkTag::ANI, "null wantCls");
83 return nullptr;
84 }
85 if ((status = env->Class_FindMethod(cls, "<ctor>", ":V", &method)) != ANI_OK) {
86 TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
87 return nullptr;
88 }
89 if ((status = env->Object_New(cls, method, &object)) != ANI_OK) {
90 TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
91 return nullptr;
92 }
93 if (object == nullptr) {
94 TAG_LOGE(AAFwkTag::ANI, "null object");
95 return nullptr;
96 }
97
98 auto elementName = want.GetElement();
99 SetFieldStringByName(env, cls, object, "deviceId", elementName.GetDeviceID());
100 SetFieldStringByName(env, cls, object, "bundleName", elementName.GetBundleName());
101 SetFieldStringByName(env, cls, object, "abilityName", elementName.GetAbilityName());
102 SetFieldStringByName(env, cls, object, "moduleName", elementName.GetModuleName());
103 SetFieldStringByName(env, cls, object, "uri", want.GetUriString());
104 SetFieldStringByName(env, cls, object, "type", want.GetType());
105 SetFieldDoubleByName(env, cls, object, "flags", want.GetFlags());
106 SetFieldStringByName(env, cls, object, "action", want.GetAction());
107 InnerWrapWantParams(env, cls, object, want.GetParams());
108 SetFieldArrayStringByName(env, cls, object, "entities", want.GetEntities());
109
110 return object;
111 }
112
WrapWantParams(ani_env * env,const AAFwk::WantParams & wantParams)113 ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams)
114 {
115 if (env == nullptr) {
116 TAG_LOGE(AAFwkTag::ANI, "null env");
117 return nullptr;
118 }
119 ani_status status = ANI_ERROR;
120 ani_class cls = nullptr;
121 if ((status = env->FindClass(TOOL_CLASS_NAME, &cls)) != ANI_OK) {
122 TAG_LOGE(AAFwkTag::ANI, "FindClass RecordSerializeTool failed, status: %{public}d", status);
123 return nullptr;
124 }
125 if (cls == nullptr) {
126 TAG_LOGE(AAFwkTag::ANI, "RecordSerializeTool class null");
127 return nullptr;
128 }
129 ani_static_method parseNoThrowMethod = nullptr;
130 status = env->Class_FindStaticMethod(cls, "parseNoThrow", nullptr, &parseNoThrowMethod);
131 if (status != ANI_OK) {
132 TAG_LOGE(AAFwkTag::ANI, "failed to get parseNoThrow method, status: %{public}d", status);
133 return nullptr;
134 }
135
136 nlohmann::json wantParamsJson = wantParams;
137 std::string wantParamsString = wantParamsJson.dump();
138 ani_string wantParamsAniString;
139 status = env->String_NewUTF8(wantParamsString.c_str(), wantParamsString.length(), &wantParamsAniString);
140 if (status != ANI_OK) {
141 TAG_LOGE(AAFwkTag::ANI, "String_NewUTF8 wantParamsString failed, status: %{public}d", status);
142 return nullptr;
143 }
144
145 ani_ref wantParamsRef = nullptr;
146 status = env->Class_CallStaticMethod_Ref(cls, parseNoThrowMethod, &wantParamsRef, wantParamsAniString);
147 if (status != ANI_OK) {
148 TAG_LOGE(AAFwkTag::ANI, "failed to call parseNoThrow method, status: %{public}d", status);
149 return nullptr;
150 }
151 return wantParamsRef;
152 }
153
InnerWrapWantParamsString(ani_env * env,ani_object object,const std::string & key,const AAFwk::WantParams & wantParams)154 bool InnerWrapWantParamsString(
155 ani_env *env, ani_object object, const std::string &key, const AAFwk::WantParams &wantParams)
156 {
157 if (env == nullptr) {
158 TAG_LOGE(AAFwkTag::ANI, "null env");
159 return false;
160 }
161 auto value = wantParams.GetParam(key);
162 AAFwk::IString *ao = AAFwk::IString::Query(value);
163 return ao != nullptr;
164 }
165
UnwrapElementName(ani_env * env,ani_object param,ElementName & elementName)166 bool UnwrapElementName(ani_env *env, ani_object param, ElementName &elementName)
167 {
168 if (env == nullptr) {
169 TAG_LOGE(AAFwkTag::ANI, "null env");
170 return false;
171 }
172 std::string deviceId;
173 if (GetFieldStringByName(env, param, "deviceId", deviceId)) {
174 elementName.SetDeviceID(deviceId);
175 }
176
177 std::string bundleName;
178 if (GetFieldStringByName(env, param, "bundleName", bundleName)) {
179 elementName.SetBundleName(bundleName);
180 }
181
182 std::string abilityName;
183 if (GetFieldStringByName(env, param, "abilityName", abilityName)) {
184 elementName.SetAbilityName(abilityName);
185 }
186
187 std::string moduleName;
188 if (GetFieldStringByName(env, param, "moduleName", moduleName)) {
189 elementName.SetModuleName(moduleName);
190 }
191 return true;
192 }
193
UnwrapWant(ani_env * env,ani_object param,AAFwk::Want & want)194 bool UnwrapWant(ani_env *env, ani_object param, AAFwk::Want &want)
195 {
196 TAG_LOGD(AAFwkTag::ANI, "UnwrapWant called");
197 if (env == nullptr) {
198 TAG_LOGE(AAFwkTag::ANI, "null env");
199 return false;
200 }
201 std::string action;
202 if (GetFieldStringByName(env, param, "action", action)) {
203 TAG_LOGD(AAFwkTag::ANI, "action %{public}s", action.c_str());
204 want.SetAction(action);
205 }
206
207 std::string uri = "";
208 if (GetFieldStringByName(env, param, "uri", uri)) {
209 TAG_LOGD(AAFwkTag::ANI, "uri %{public}s", uri.c_str());
210 want.SetUri(uri);
211 }
212
213 double flags = 0.0;
214 if (GetFieldDoubleByName(env, param, "flags", flags)) {
215 TAG_LOGD(AAFwkTag::ANI, "flags %{public}f", flags);
216 want.SetFlags(static_cast<int>(flags));
217 }
218
219 std::string type = "";
220 if (GetFieldStringByName(env, param, "type", type)) {
221 TAG_LOGD(AAFwkTag::ANI, "type %{public}s", type.c_str());
222 want.SetType(type);
223 }
224
225 ElementName natElementName;
226 UnwrapElementName(env, param, natElementName);
227 want.SetElementName(natElementName.GetDeviceID(), natElementName.GetBundleName(), natElementName.GetAbilityName(),
228 natElementName.GetModuleName());
229
230 std::vector<std::string> valueStringList;
231 if (GetFieldStringArrayByName(env, param, "entities", valueStringList)) {
232 for (size_t i = 0; i < valueStringList.size(); i++) {
233 want.AddEntity(valueStringList[i]);
234 }
235 }
236 TAG_LOGD(AAFwkTag::ANI,
237 "DeviceID %{public}s, BundleName %{public}s, AbilityName %{public}s, ModuleName %{public}s",
238 natElementName.GetDeviceID().c_str(), natElementName.GetBundleName().c_str(),
239 natElementName.GetAbilityName().c_str(), natElementName.GetModuleName().c_str());
240
241 AAFwk::WantParams wantParams;
242 if (InnerUnwrapWantParams(env, param, wantParams)) {
243 want.SetParams(wantParams);
244 }
245 return true;
246 }
247
UnwrapWantParams(ani_env * env,ani_ref param,AAFwk::WantParams & wantParams)248 bool UnwrapWantParams(ani_env *env, ani_ref param, AAFwk::WantParams &wantParams)
249 {
250 if (env == nullptr) {
251 TAG_LOGE(AAFwkTag::ANI, "null env");
252 return false;
253 }
254 ani_status status = ANI_ERROR;
255 ani_class cls = nullptr;
256 if ((status = env->FindClass(TOOL_CLASS_NAME, &cls)) != ANI_OK) {
257 TAG_LOGE(AAFwkTag::ANI, "FindClass RecordSerializeTool failed, status: %{public}d", status);
258 return false;
259 }
260 if (cls == nullptr) {
261 TAG_LOGE(AAFwkTag::ANI, "RecordSerializeTool class null");
262 return false;
263 }
264 ani_static_method stringifyMethod = nullptr;
265 status = env->Class_FindStaticMethod(cls, "stringifyNoThrow", nullptr, &stringifyMethod);
266 if (status != ANI_OK) {
267 TAG_LOGE(AAFwkTag::ANI, "failed to get stringifyNoThrow method, status: %{public}d", status);
268 return false;
269 }
270 ani_ref wantParamsAniString;
271 status = env->Class_CallStaticMethod_Ref(cls, stringifyMethod, &wantParamsAniString, param);
272 if (status != ANI_OK) {
273 TAG_LOGE(AAFwkTag::ANI, "failed to call stringifyNoThrow method, status: %{public}d", status);
274 return false;
275 }
276 std::string wantParamsString;
277 if (!GetStdString(env, reinterpret_cast<ani_string>(wantParamsAniString), wantParamsString)) {
278 TAG_LOGE(AAFwkTag::ANI, "GetStdString failed");
279 return false;
280 }
281 if (wantParamsString.empty()) {
282 TAG_LOGE(AAFwkTag::ANI, "wantParamsString empty");
283 return false;
284 }
285 nlohmann::json wantParamsJson = nlohmann::json::parse(wantParamsString, nullptr, false);
286 if (wantParamsJson.is_discarded()) {
287 TAG_LOGE(AAFwkTag::ANI, "Failed to parse json string");
288 return false;
289 }
290 from_json(wantParamsJson, wantParams);
291 return true;
292 }
293
GetAbilityResultClass(ani_env * env,ani_class & cls)294 bool GetAbilityResultClass(ani_env *env, ani_class &cls)
295 {
296 ani_status status = env->FindClass(INNER_CLASS_NAME, &cls);
297 if (status != ANI_OK || cls == nullptr) {
298 TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
299 return false;
300 }
301 return true;
302 }
303
GetResultCode(ani_env * env,ani_object param,ani_class cls,int & resultCode)304 bool GetResultCode(ani_env *env, ani_object param, ani_class cls, int &resultCode)
305 {
306 ani_method method = nullptr;
307 ani_status status = env->Class_FindMethod(cls, "<get>resultCode", nullptr, &method);
308 if (status != ANI_OK) {
309 TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
310 return false;
311 }
312 ani_double dResultCode = 0.0;
313 status = env->Object_CallMethod_Double(param, method, &dResultCode);
314 if (status != ANI_OK) {
315 TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
316 return false;
317 }
318 resultCode = static_cast<int>(dResultCode);
319 return true;
320 }
321
GetWantReference(ani_env * env,ani_object param,ani_class cls,ani_ref & wantRef)322 bool GetWantReference(ani_env *env, ani_object param, ani_class cls, ani_ref &wantRef)
323 {
324 ani_method method {};
325 ani_status status = env->Class_FindMethod(cls, "<get>want", nullptr, &method);
326 if (status != ANI_OK) {
327 TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
328 return false;
329 }
330 status = env->Object_CallMethod_Ref(param, method, &wantRef);
331 if (status != ANI_OK) {
332 TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
333 return false;
334 }
335 ani_boolean isUndefined = ANI_TRUE;
336 status = env->Reference_IsUndefined(wantRef, &isUndefined);
337 if (status != ANI_OK || isUndefined) {
338 TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status);
339 return false;
340 }
341 return true;
342 }
343
UnWrapAbilityResult(ani_env * env,ani_object param,int & resultCode,AAFwk::Want & want)344 bool UnWrapAbilityResult(ani_env *env, ani_object param, int &resultCode, AAFwk::Want &want)
345 {
346 TAG_LOGD(AAFwkTag::ANI, "called");
347 if (env == nullptr) {
348 TAG_LOGE(AAFwkTag::ANI, "null env");
349 return false;
350 }
351 ani_class cls = nullptr;
352 if (!GetAbilityResultClass(env, cls)) {
353 return false;
354 }
355 if (!GetResultCode(env, param, cls, resultCode)) {
356 return false;
357 }
358 ani_ref wantRef = nullptr;
359 if (!GetWantReference(env, param, cls, wantRef)) {
360 return false;
361 }
362 return UnwrapWant(env, reinterpret_cast<ani_object>(wantRef), want);
363 }
364
WrapElementName(ani_env * env,const AppExecFwk::ElementName & elementNameParam)365 ani_object WrapElementName(ani_env *env, const AppExecFwk::ElementName &elementNameParam)
366 {
367 TAG_LOGD(AAFwkTag::ANI, "WrapElementName");
368 if (env == nullptr) {
369 TAG_LOGE(AAFwkTag::ANI, "null env");
370 return nullptr;
371 }
372 ani_class elementNameObj = nullptr;
373 ani_status status = ANI_ERROR;
374 ani_method method = nullptr;
375 ani_object object = nullptr;
376 if ((status = env->FindClass(ELEMENTNAME_CLASS_NAME, &elementNameObj)) != ANI_OK || elementNameObj == nullptr) {
377 TAG_LOGE(AAFwkTag::ANI, "FindClass status: %{public}d or null elementNameObj", status);
378 return nullptr;
379 }
380 if ((status = env->Class_FindMethod(elementNameObj, "<ctor>", ":V", &method)) != ANI_OK || method == nullptr) {
381 TAG_LOGE(AAFwkTag::ANI, "Class_FindMethod status: %{public}d or null method", status);
382 return nullptr;
383 }
384 if ((status = env->Object_New(elementNameObj, method, &object)) != ANI_OK || object == nullptr) {
385 TAG_LOGE(AAFwkTag::ANI, "Object_New status: %{public}d or null object", status);
386 return nullptr;
387 }
388 return WrapElementNameInner(env, elementNameObj, object, elementNameParam);
389 }
390
WrapElementNameInner(ani_env * env,ani_class elementNameObj,ani_object object,const AppExecFwk::ElementName & elementNameParam)391 ani_object WrapElementNameInner(ani_env *env, ani_class elementNameObj, ani_object object,
392 const AppExecFwk::ElementName &elementNameParam)
393 {
394 TAG_LOGD(AAFwkTag::ANI, "WrapElementNameInner");
395 if (env == nullptr || elementNameObj == nullptr || object == nullptr) {
396 TAG_LOGE(AAFwkTag::ANI, "invalid args");
397 return nullptr;
398 }
399 if (!SetFieldStringByName(env, elementNameObj, object, "bundleName", elementNameParam.GetBundleName())) {
400 TAG_LOGE(AAFwkTag::ANI, "set bundleName failed");
401 return nullptr;
402 }
403 if (!SetFieldStringByName(env, elementNameObj, object, "abilityName", elementNameParam.GetAbilityName())) {
404 TAG_LOGE(AAFwkTag::ANI, "set abilityName failed");
405 return nullptr;
406 }
407 if (!SetFieldStringByName(env, elementNameObj, object, "deviceId", elementNameParam.GetDeviceID())) {
408 TAG_LOGE(AAFwkTag::ANI, "set deviceId failed");
409 }
410 if (!SetFieldStringByName(env, elementNameObj, object, "moduleName", elementNameParam.GetModuleName())) {
411 TAG_LOGE(AAFwkTag::ANI, "set moduleName failed");
412 }
413 if (!SetFieldStringByName(env, elementNameObj, object, "uri", elementNameParam.GetURI())) {
414 TAG_LOGE(AAFwkTag::ANI, "set uri failed");
415 }
416 if (!SetFieldStringByName(env, elementNameObj, object, "shortName", elementNameParam.GetURI())) {
417 TAG_LOGE(AAFwkTag::ANI, "set shortName failed");
418 }
419 return object;
420 }
421
422 } // namespace AppExecFwk
423 } // namespace OHOS
424