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