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 "ets_uri_perm_mgr.h"
17
18 #include "ability_business_error.h"
19 #include "ability_manager_errors.h"
20 #include "ability_runtime_error_util.h"
21 #include "ani_enum_convert.h"
22 #include "hilog_tag_wrapper.h"
23 #include "ipc_skeleton.h"
24 #include "js_error_utils.h"
25 #include "js_runtime_utils.h"
26 #include "napi_common_util.h"
27 #include "parameters.h"
28 #include "tokenid_kit.h"
29 #include "uri.h"
30 #include "uri_permission_manager_client.h"
31 #include "ets_error_utils.h"
32
33 namespace OHOS {
34 namespace AbilityRuntime {
35 namespace {
36 constexpr const char* WRAPPER_CLASS_NAME = "Lutils/AbilityUtils/AsyncCallbackWrapper;";
37 constexpr const char* ERROR_CLASS_NAME = "Lescompat/Error;";
38 constexpr const char* BUSINESS_ERROR_CLASS_NAME = "L@ohos/base/BusinessError;";
39 constexpr const char *INVOKE_METHOD_NAME = "invoke";
40 constexpr const int32_t ERR_OK = 0;
41 constexpr const int32_t ERR_FAILURE = -1;
42 constexpr const char* NOT_SYSTEM_APP = "The application is not system-app, can not use system-api.";
43
CreateDouble(ani_env * env,int32_t res)44 ani_object CreateDouble(ani_env *env, int32_t res)
45 {
46 if (env == nullptr) {
47 return nullptr;
48 }
49 static const char *className = "Lstd/core/Double;";
50 ani_class cls;
51 if (ANI_OK != env->FindClass(className, &cls)) {
52 TAG_LOGE(AAFwkTag::URIPERMMGR, "create double error");
53 return nullptr;
54 }
55
56 if (cls == nullptr) {
57 return nullptr;
58 }
59 ani_method ctor;
60 env->Class_FindMethod(cls, "<ctor>", "D:V", &ctor);
61 if (ctor == nullptr) {
62 return nullptr;
63 }
64 ani_object obj;
65 env->Object_New(cls, ctor, &obj, ani_double(res));
66 return obj;
67 }
68
69 }
70
GetStdString(ani_env * env,ani_string str)71 static std::string GetStdString(ani_env* env, ani_string str)
72 {
73 if (env == nullptr) {
74 return std::string();
75 }
76 std::string result;
77 ani_size sz {};
78 env->String_GetUTF8Size(str, &sz);
79 result.resize(sz + 1);
80 env->String_GetUTF8SubString(str, 0, sz, result.data(), result.size(), &sz);
81 result.resize(sz);
82 return result;
83 }
84
grantUriPermissionCallbackSync(ani_env * env,ani_string uri,ani_enum_item flagEnum,ani_string targetName,ani_double appCloneIndex,ani_object callback)85 static void grantUriPermissionCallbackSync([[maybe_unused]]ani_env *env,
86 ani_string uri, ani_enum_item flagEnum, ani_string targetName, ani_double appCloneIndex, ani_object callback)
87 {
88 TAG_LOGI(AAFwkTag::URIPERMMGR, "grantUriPermissionCallbackSync run");
89 if (env == nullptr) {
90 TAG_LOGE(AAFwkTag::URIPERMMGR, "env null");
91 return;
92 }
93 auto selfToken = IPCSkeleton::GetSelfTokenID();
94 ani_object etsErrCode = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK);
95 if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) {
96 TAG_LOGE(AAFwkTag::URIPERMMGR, "app not system-app");
97 etsErrCode = EtsErrorUtil::CreateError(env,
98 static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), NOT_SYSTEM_APP);
99 AsyncCallback(env, callback, etsErrCode, CreateDouble(env, ERR_FAILURE));
100 return;
101 }
102 std::string uriStr = GetStdString(env, uri);
103 Uri uriVec(uriStr);
104 ani_int flag = 0;
105 AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative(env, flagEnum, flag);
106 int32_t flagId = static_cast<int32_t>(flag);
107 std::string targetBundleName = GetStdString(env, targetName);
108 int32_t appCloneIndexId = static_cast<int32_t>(appCloneIndex);
109 int32_t result = ERR_OK;
110 int32_t errCode = AAFwk::UriPermissionManagerClient::GetInstance().GrantUriPermission(uriVec, flagId,
111 targetBundleName, appCloneIndexId);
112 if (errCode != ERR_OK) {
113 result = ERR_FAILURE;
114 etsErrCode = EtsErrorUtil::CreateErrorByNativeErr(env, errCode);
115 }
116
117 AsyncCallback(env, callback, etsErrCode, CreateDouble(env, result));
118 }
119
revokeUriPermissionCallbackSync(ani_env * env,ani_string uri,ani_string targetName,ani_double appCloneIndex,ani_object callback)120 static void revokeUriPermissionCallbackSync([[maybe_unused]]ani_env *env,
121 ani_string uri, ani_string targetName, ani_double appCloneIndex, ani_object callback)
122 {
123 TAG_LOGI(AAFwkTag::URIPERMMGR, "revokeUriPermissionCallbackSync run");
124 if (env == nullptr) {
125 TAG_LOGE(AAFwkTag::URIPERMMGR, "env null");
126 return;
127 }
128 auto selfToken = IPCSkeleton::GetSelfTokenID();
129 ani_object etsErrCode = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK);
130 if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) {
131 TAG_LOGE(AAFwkTag::URIPERMMGR, "app not system-app");
132 etsErrCode = EtsErrorUtil::CreateError(env,
133 static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), NOT_SYSTEM_APP);
134 AsyncCallback(env, callback, etsErrCode, CreateDouble(env, ERR_FAILURE));
135 return;
136 }
137 std::string uriStr = GetStdString(env, uri);
138 Uri uriVec(uriStr);
139 std::string targetBundleName = GetStdString(env, targetName);
140 int32_t result = ERR_OK;
141 int32_t errCode = AAFwk::UriPermissionManagerClient::GetInstance().RevokeUriPermissionManually(uriVec,
142 targetBundleName, appCloneIndex);
143 if (errCode != ERR_OK) {
144 result = ERR_FAILURE;
145 etsErrCode = EtsErrorUtil::CreateErrorByNativeErr(env, errCode);
146 }
147 AsyncCallback(env, callback, etsErrCode, CreateDouble(env, result));
148 }
149
EtsUriPermissionManagerInit(ani_env * env)150 void EtsUriPermissionManagerInit(ani_env *env)
151 {
152 TAG_LOGI(AAFwkTag::URIPERMMGR, "EtsUriPermissionManagerInit call");
153 if (env == nullptr) {
154 TAG_LOGE(AAFwkTag::URIPERMMGR, "Invalid param");
155 return;
156 }
157 ani_namespace ns;
158 const char* targetNamespace = "L@ohos/application/uriPermissionManager/uriPermissionManager;";
159 if (env->FindNamespace(targetNamespace, &ns) != ANI_OK) {
160 TAG_LOGE(AAFwkTag::URIPERMMGR, "FindNamespace failed");
161 }
162 if (ns == nullptr) {
163 TAG_LOGE(AAFwkTag::URIPERMMGR, "ns null");
164 return;
165 }
166 std::array functions = {
167 ani_native_function {
168 "grantUriPermissionCallbackSync",
169 "Lstd/core/String;L@ohos/app/ability/wantConstant/wantConstant/Flags;Lstd/core/String;D"
170 "Lutils/AbilityUtils/AsyncCallbackWrapper;:V",
171 reinterpret_cast<void*>(grantUriPermissionCallbackSync)
172 },
173 ani_native_function {
174 "revokeUriPermissionCallbackSync",
175 "Lstd/core/String;Lstd/core/String;D"
176 "Lutils/AbilityUtils/AsyncCallbackWrapper;:V",
177 reinterpret_cast<void*>(revokeUriPermissionCallbackSync)
178 },
179 };
180 TAG_LOGI(AAFwkTag::URIPERMMGR, "EtsUriPermissionManagerInit bind functions");
181 if (env->Namespace_BindNativeFunctions(ns, functions.data(), functions.size()) != ANI_OK) {
182 TAG_LOGE(AAFwkTag::URIPERMMGR, "Namespace_BindNativeFunctions failed");
183 };
184 TAG_LOGI(AAFwkTag::URIPERMMGR, "EtsUriPermissionManagerInit end");
185 }
186
187 extern "C"{
ANI_Constructor(ani_vm * vm,uint32_t * result)188 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
189 {
190 TAG_LOGI(AAFwkTag::URIPERMMGR, "ANI_Constructor");
191 if (vm == nullptr) {
192 TAG_LOGE(AAFwkTag::URIPERMMGR, "vm null");
193 return ANI_ERROR;
194 }
195 if (result == nullptr) {
196 TAG_LOGE(AAFwkTag::URIPERMMGR, "result null");
197 return ANI_ERROR;
198 }
199 ani_env *env = nullptr;
200 ani_status status = ANI_ERROR;
201 status = vm->GetEnv(ANI_VERSION_1, &env);
202 if (status != ANI_OK) {
203 TAG_LOGI(AAFwkTag::URIPERMMGR, "GetEnv failed status: %{public}d", status);
204 return ANI_NOT_FOUND;
205 }
206
207 EtsUriPermissionManagerInit(env);
208 *result = ANI_VERSION_1;
209 TAG_LOGI(AAFwkTag::URIPERMMGR, "ANI_Constructor finish");
210 return ANI_OK;
211 }
212 }
213
AsyncCallback(ani_env * env,ani_object call,ani_object error,ani_object result)214 bool AsyncCallback(ani_env *env, ani_object call, ani_object error, ani_object result)
215 {
216 ani_status status = ANI_ERROR;
217 ani_class clsCall {};
218
219 if (env == nullptr) {
220 TAG_LOGE(AAFwkTag::URIPERMMGR, "env null");
221 return false;
222 }
223
224 if ((status = env->FindClass(WRAPPER_CLASS_NAME, &clsCall)) != ANI_OK) {
225 TAG_LOGE(AAFwkTag::URIPERMMGR, "status: %{public}d", status);
226 return false;
227 }
228 ani_method method = {};
229 if ((status = env->Class_FindMethod(
230 clsCall, INVOKE_METHOD_NAME, "L@ohos/base/BusinessError;Lstd/core/Object;:V", &method)) != ANI_OK) {
231 TAG_LOGE(AAFwkTag::URIPERMMGR, "status: %{public}d", status);
232 return false;
233 }
234 if (method == nullptr) {
235 TAG_LOGE(AAFwkTag::URIPERMMGR, "method null");
236 return false;
237 }
238 if (result == nullptr) {
239 ani_ref nullRef = nullptr;
240 env->GetNull(&nullRef);
241 result = reinterpret_cast<ani_object>(nullRef);
242 }
243 if ((status = env->Object_CallMethod_Void(call, method, error, result)) != ANI_OK) {
244 TAG_LOGE(AAFwkTag::URIPERMMGR, "status: %{public}d", status);
245 return false;
246 }
247 return true;
248 }
249
WrapError(ani_env * env,const std::string & msg)250 ani_object WrapError(ani_env *env, const std::string &msg)
251 {
252 ani_class cls {};
253 ani_method method {};
254 ani_object obj = nullptr;
255 ani_status status = ANI_ERROR;
256 if (env == nullptr) {
257 TAG_LOGE(AAFwkTag::URIPERMMGR, "null env");
258 return nullptr;
259 }
260 ani_string aniMsg = GetAniString(env, msg);
261 ani_ref undefRef;
262 env->GetUndefined(&undefRef);
263 if ((status = env->FindClass(ERROR_CLASS_NAME, &cls)) != ANI_OK) {
264 TAG_LOGE(AAFwkTag::URIPERMMGR, "statys: %{public}d", status);
265 return nullptr;
266 }
267 if ((status = env->Class_FindMethod(cls, "<ctor>", "Lstd/core/String;Lescompat/ErrorOptions;:V", &method)) !=
268 ANI_OK) {
269 TAG_LOGE(AAFwkTag::URIPERMMGR, "status: %{public}d", status);
270 return nullptr;
271 }
272 if ((status = env->Object_New(cls, method, &obj, aniMsg, undefRef)) != ANI_OK) {
273 TAG_LOGE(AAFwkTag::URIPERMMGR, "status: %{public}d", status);
274 return nullptr;
275 }
276 return obj;
277 }
278
GetAniString(ani_env * env,const std::string & str)279 ani_string GetAniString(ani_env *env, const std::string &str)
280 {
281 ani_string aniStr = nullptr;
282 ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr);
283 if (status != ANI_OK) {
284 TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status);
285 return nullptr;
286 }
287 return aniStr;
288 }
289
WrapBusinessError(ani_env * env,int32_t code)290 ani_object WrapBusinessError(ani_env *env, int32_t code)
291 {
292 ani_class cls {};
293 ani_method method {};
294 ani_object obj = nullptr;
295 ani_status status = ANI_ERROR;
296 if (env == nullptr) {
297 TAG_LOGE(AAFwkTag::UIABILITY, "null env");
298 return nullptr;
299 }
300 if ((status = env->FindClass(BUSINESS_ERROR_CLASS_NAME, &cls)) != ANI_OK) {
301 TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status);
302 return nullptr;
303 }
304 if ((status = env->Class_FindMethod(cls, "<ctor>", "DLescompat/Error;:V", &method)) != ANI_OK) {
305 TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status);
306 return nullptr;
307 }
308 ani_object error = WrapError(env, GetErrMsg(code));
309 if (error == nullptr) {
310 TAG_LOGE(AAFwkTag::UIABILITY, "error nulll");
311 return nullptr;
312 }
313 ani_double dCode(code);
314 if ((status = env->Object_New(cls, method, &obj, dCode, error)) != ANI_OK) {
315 TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status);
316 return nullptr;
317 }
318 return obj;
319 }
320
GetErrMsg(int32_t err,const std::string & permission)321 std::string GetErrMsg(int32_t err, const std::string &permission)
322 {
323 auto errCode = GetJsErrorCodeByNativeError(err);
324 auto errMsg = (errCode == AbilityErrorCode::ERROR_CODE_PERMISSION_DENIED && !permission.empty())
325 ? GetNoPermissionErrorMsg(permission)
326 : GetErrorMsg(errCode);
327 return errMsg;
328 }
329
330 } // namespace AbilityRuntime
331 } // namespace OHOS