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 #include "ani.h"
16 #include "ani_plugin_component_util.h"
17 #include "core/common/container.h"
18
AceCreateAsyncJSCallbackInfo(ani_env * env)19 ACEAsyncJSCallbackInfo* AceCreateAsyncJSCallbackInfo(ani_env* env)
20 {
21 auto containerId = OHOS::Ace::Container::CurrentId();
22 ACEAsyncJSCallbackInfo* asyncCallbackInfo = new ACEAsyncJSCallbackInfo {
23 .cbInfo = {
24 .env = env,
25 .callback = nullptr,
26 .containerId = containerId,
27 },
28 .ability = nullptr,
29 };
30 return asyncCallbackInfo;
31 }
32
AceFreeAsyncJSCallbackInfo(ACEAsyncJSCallbackInfo ** asyncCallbackInfo)33 void AceFreeAsyncJSCallbackInfo(ACEAsyncJSCallbackInfo** asyncCallbackInfo)
34 {
35 if (asyncCallbackInfo == nullptr) {
36 return;
37 }
38 if (*asyncCallbackInfo == nullptr) {
39 return;
40 }
41
42 if ((*asyncCallbackInfo)->cbInfo.callback != nullptr && (*asyncCallbackInfo)->cbInfo.env != nullptr) {
43 (*asyncCallbackInfo)->cbInfo.callback = nullptr;
44 (*asyncCallbackInfo)->cbInfo.env = nullptr;
45 }
46
47 delete (*asyncCallbackInfo);
48 *asyncCallbackInfo = nullptr;
49 }
50
AceIsSameFuncFromANI(ACECallbackInfo & left,ACECallbackInfo & right)51 bool AceIsSameFuncFromANI(ACECallbackInfo& left, ACECallbackInfo& right)
52 {
53 if (left.env == nullptr && right.env == nullptr) {
54 return true;
55 }
56 if (left.env != right.env || left.containerId != right.containerId) {
57 return false;
58 }
59 if (left.callback == nullptr && right.callback == nullptr) {
60 return true;
61 }
62 ani_boolean rs;
63 left.env->Reference_StrictEquals(left.callback, right.callback, &rs);
64 return rs == ANI_TRUE;
65 }
66
CreateInt(ani_env * env,ani_int value)67 ani_ref CreateInt(ani_env* env, ani_int value)
68 {
69 ani_class cls;
70 env->FindClass("Lstd/core/Int;", &cls);
71 ani_method ctor;
72 env->Class_FindMethod(cls, "<ctor>", "I:V", &ctor);
73 ani_object rs;
74 env->Object_New(cls, ctor, &rs, value);
75 return rs;
76 }
77
AceWrapStringToAni(ani_env * env,std::string str)78 ani_string AceWrapStringToAni(ani_env* env, std::string str)
79 {
80 ani_string aniStr;
81 ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr);
82 if (ANI_OK != status) {
83 LOGE("Can not convert string to ani_string.");
84 return nullptr;
85 }
86 return aniStr;
87 }
88
AceWrapStringToObject(ani_env * env,const std::string str)89 ani_ref AceWrapStringToObject(ani_env* env, const std::string str)
90 {
91 ani_ref undefinedResult;
92 env->GetUndefined(&undefinedResult);
93 ani_class cls = nullptr;
94 if (ANI_OK != env->FindClass("L@ohos/app/ability/Want/RecordSerializeTool;", &cls)) {
95 LOGE("plugin-ani FindClass RecordSerializeTool failed");
96 return undefinedResult;
97 }
98 if (cls == nullptr) {
99 LOGE("plugin-ani RecordSerializeTool class null");
100 return undefinedResult;
101 }
102 ani_static_method parseMethod = nullptr;
103 if (ANI_OK != env->Class_FindStaticMethod(cls, "parseNoThrow", nullptr, &parseMethod)) {
104 LOGE("plugin-ani failed to get parseNoThrow method");
105 return undefinedResult;
106 }
107 ani_ref kvObjectAniString;
108 if (ANI_OK != env->Class_CallStaticMethod_Ref(cls, parseMethod, &kvObjectAniString, AceWrapStringToAni(env, str))) {
109 LOGE("plugin-ani failed to call parseNoThrow method");
110 return undefinedResult;
111 }
112 ani_boolean isUndefined = true;
113 if (ANI_OK != env->Reference_IsUndefined(kvObjectAniString, &isUndefined) || isUndefined) {
114 LOGE("plugin-ani parseNoThrow is null");
115 return undefinedResult;
116 }
117 return kvObjectAniString;
118 }
119
AniStringToNativeString(ani_env * env,ani_string ani_str)120 std::string AniStringToNativeString(ani_env* env, ani_string ani_str)
121 {
122 ani_size strSize;
123 env->String_GetUTF8Size(ani_str, &strSize);
124
125 std::vector<char> buffer(strSize + 1); // +1 for null terminator
126 char* utf8Buffer = buffer.data();
127
128 ani_size bytes_written = 0;
129 env->String_GetUTF8(ani_str, utf8Buffer, strSize + 1, &bytes_written);
130
131 utf8Buffer[bytes_written] = '\0';
132 std::string content = std::string(utf8Buffer);
133 return content;
134 }
135
GetAniKVObjectPropertyByName(ani_env * env,ani_object parameters,std::string propertyName,std::string & propertyValue)136 ani_status GetAniKVObjectPropertyByName(ani_env* env, ani_object parameters, std::string propertyName,
137 std::string &propertyValue)
138 {
139 ani_ref kvObj;
140 if (ANI_OK != env->Object_GetPropertyByName_Ref(parameters, propertyName.c_str(), &kvObj)) {
141 LOGE("plugin-ani GetAniKVObjectPropertyByName %{public}s error", propertyName.c_str());
142 return ANI_ERROR;
143 }
144 ani_boolean isUndefined = true;
145 if (ANI_OK != env->Reference_IsUndefined(kvObj, &isUndefined) || isUndefined) {
146 LOGE("plugin-ani GetAniKVObjectPropertyByName %{public}s is null", propertyName.c_str());
147 return ANI_ERROR;
148 }
149 ani_class cls = nullptr;
150 if (ANI_OK != env->FindClass("L@ohos/app/ability/Want/RecordSerializeTool;", &cls)) {
151 LOGE("plugin-ani FindClass RecordSerializeTool failed");
152 return ANI_ERROR;
153 }
154 if (cls == nullptr) {
155 LOGE("plugin-ani RecordSerializeTool class null");
156 return ANI_ERROR;
157 }
158 ani_static_method stringifyMethod = nullptr;
159 if (ANI_OK != env->Class_FindStaticMethod(cls, "stringifyNoThrow", nullptr, &stringifyMethod)) {
160 LOGE("plugin-ani failed to get stringifyNoThrow method");
161 return ANI_ERROR;
162 }
163 ani_ref kvObjectAniString;
164 if (ANI_OK != env->Class_CallStaticMethod_Ref(cls, stringifyMethod, &kvObjectAniString, kvObj)) {
165 LOGE("plugin-ani failed to call stringifyNoThrow method");
166 return ANI_ERROR;
167 }
168 if (ANI_OK != env->Reference_IsUndefined(kvObjectAniString, &isUndefined) || isUndefined) {
169 LOGE("plugin-ani GetAniKVObjectPropertyByName %{public}s is null", propertyName.c_str());
170 return ANI_ERROR;
171 }
172 propertyValue = AniStringToNativeString(env, reinterpret_cast<ani_string>(kvObjectAniString));
173 return ANI_OK;
174 }
175
GetAniStringPropertyByName(ani_env * env,ani_object parameters,std::string propertyName,std::string & propertyValue)176 ani_status GetAniStringPropertyByName(ani_env* env, ani_object parameters, std::string propertyName,
177 std::string &propertyValue)
178 {
179 ani_ref valueAni;
180 if (ANI_OK != env->Object_GetPropertyByName_Ref(parameters, propertyName.c_str(), &valueAni)) {
181 LOGE("plugin-ani GetPropertyByName %{public}s error", propertyName.c_str());
182 return ANI_ERROR;
183 }
184 ani_boolean isUndefined = true;
185 if (ANI_OK != env->Reference_IsUndefined(valueAni, &isUndefined) || isUndefined) {
186 LOGE("plugin-ani GetPropertyByName %{public}s is null", propertyName.c_str());
187 return ANI_ERROR;
188 }
189 propertyValue = AniStringToNativeString(env, reinterpret_cast<ani_string>(valueAni));
190 return ANI_OK;
191 }