• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "at_manager_impl.h"
17 #include "ability_access_ctrl_common.h"
18 #include "ability.h"
19 #include "ability_manager_client.h"
20 #include "access_token.h"
21 #include "access_token_error.h"
22 #include "macro.h"
23 #include "parameter.h"
24 #include "token_setproc.h"
25 #include "want.h"
26 
27 using namespace OHOS::FFI;
28 using namespace OHOS::Security::AccessToken;
29 
30 namespace OHOS {
31 namespace CJSystemapi {
32 
33 std::mutex g_lockForPermStateChangeRegisters;
34 std::vector<RegisterPermStateChangeInfo*> g_permStateChangeRegisters;
35 std::mutex g_lockCache;
36 std::map<std::string, GrantStatusCache> g_cache;
37 static PermissionParamCache g_paramCache;
38 std::mutex g_lockForPermRequestCallbacks;
39 static const char* PERMISSION_STATUS_CHANGE_KEY = "accesstoken.permission.change";
40 
41 const std::string GRANT_ABILITY_BUNDLE_NAME = "com.ohos.permissionmanager";
42 const std::string GRANT_ABILITY_ABILITY_NAME = "com.ohos.permissionmanager.GrantAbility";
43 const std::string PERMISSION_KEY = "ohos.user.grant.permission";
44 const std::string STATE_KEY = "ohos.user.grant.permission.state";
45 const std::string TOKEN_KEY = "ohos.ability.params.token";
46 const std::string CALLBACK_KEY = "ohos.ability.params.callback";
47 const std::string RESULT_KEY = "ohos.user.grant.permission.result";
48 
49 const std::string WINDOW_RECTANGLE_LEFT_KEY = "ohos.ability.params.request.left";
50 const std::string WINDOW_RECTANGLE_TOP_KEY = "ohos.ability.params.request.top";
51 const std::string WINDOW_RECTANGLE_HEIGHT_KEY = "ohos.ability.params.request.height";
52 const std::string WINDOW_RECTANGLE_WIDTH_KEY = "ohos.ability.params.request.width";
53 const std::string REQUEST_TOKEN_KEY = "ohos.ability.params.request.token";
54 
55 static int32_t g_curRequestCode = 0;
56 
57 static constexpr int32_t VALUE_MAX_LEN = 32;
58 static constexpr int32_t MAX_WAIT_TIME = 1000;
59 
60 extern "C" {
GetCjErrorCode(uint32_t errCode)61 static int32_t GetCjErrorCode(uint32_t errCode)
62 {
63     int32_t cjCode;
64     switch (errCode) {
65         case OHOS::Security::AccessToken::ERR_PERMISSION_DENIED:
66             cjCode = CJ_ERROR_PERMISSION_DENIED;
67             break;
68         case ERR_NOT_SYSTEM_APP:
69             cjCode = CJ_ERROR_NOT_SYSTEM_APP;
70             break;
71         case ERR_PARAM_INVALID:
72             cjCode = CJ_ERROR_PARAM_INVALID;
73             break;
74         case ERR_TOKENID_NOT_EXIST:
75             cjCode = CJ_ERROR_TOKENID_NOT_EXIST;
76             break;
77         case ERR_PERMISSION_NOT_EXIST:
78             cjCode = CJ_ERROR_PERMISSION_NOT_EXIST;
79             break;
80         case ERR_INTERFACE_NOT_USED_TOGETHER:
81         case ERR_CALLBACK_ALREADY_EXIST:
82             cjCode = CJ_ERROR_NOT_USE_TOGETHER;
83             break;
84         case ERR_CALLBACKS_EXCEED_LIMITATION:
85             cjCode = CJ_ERROR_REGISTERS_EXCEED_LIMITATION;
86             break;
87         case ERR_IDENTITY_CHECK_FAILED:
88             cjCode = CJ_ERROR_PERMISSION_OPERATION_NOT_ALLOWED;
89             break;
90         case ERR_SERVICE_ABNORMAL:
91         case ERROR_IPC_REQUEST_FAIL:
92         case ERR_READ_PARCEL_FAILED:
93         case ERR_WRITE_PARCEL_FAILED:
94             cjCode = CJ_ERROR_SERVICE_NOT_RUNNING;
95             break;
96         case ERR_MALLOC_FAILED:
97             cjCode = CJ_ERROR_OUT_OF_MEMORY;
98             break;
99         default:
100             cjCode = CJ_ERROR_INNER;
101             break;
102     }
103     LOGI("GetCjErrorCode nativeCode(%{public}d) cjCode(%{public}d).", errCode, cjCode);
104     return cjCode;
105 }
106 
IsCurrentThread(std::thread::id threadId)107 static bool IsCurrentThread(std::thread::id threadId)
108 {
109     std::thread::id currentThread = std::this_thread::get_id();
110     if (threadId != currentThread) {
111         LOGE("Ref can not be compared, different threadId!");
112         return false;
113     }
114     return true;
115 }
116 
CompareCallbackRef(int64_t subscriberRef,int64_t unsubscriberRef,std::thread::id threadId)117 static bool CompareCallbackRef(int64_t subscriberRef, int64_t unsubscriberRef, std::thread::id threadId)
118 {
119     if (!IsCurrentThread(threadId)) {
120         return false;
121     }
122     return subscriberRef == unsubscriberRef;
123 }
124 
CArrStringToVector(const CArrString & cArr)125 static std::vector<std::string> CArrStringToVector(const CArrString& cArr)
126 {
127     LOGI("ACCESS_CTRL_TEST:: CArrStringToVector start");
128     std::vector<std::string> ret;
129     for (int64_t i = 0; i < cArr.size; i++) {
130         ret.emplace_back(std::string(cArr.head[i]));
131     }
132     LOGI("ACCESS_CTRL_TEST:: CArrStringToVector end");
133     return ret;
134 }
135 
MallocCString(const std::string & stdString)136 char* MallocCString(const std::string& stdString)
137 {
138     if (stdString.empty()) {
139         return nullptr;
140     }
141     auto length = stdString.length() + 1;
142     char* ret = static_cast<char*>(malloc(sizeof(char) * length));
143     if (ret == nullptr) {
144         LOGE("MallocCString: malloc failed!");
145         return nullptr;
146     }
147     return std::char_traits<char>::copy(ret, stdString.c_str(), length);
148 }
149 
VectorToCArrString(const std::vector<std::string> & vec)150 static char** VectorToCArrString(const std::vector<std::string>& vec)
151 {
152     char** result = static_cast<char**>(malloc(sizeof(char*) * vec.size()));
153     if (result == nullptr) {
154         LOGE("VectorToCArrString: malloc failed!");
155         return nullptr;
156     }
157     for (size_t i = 0; i < vec.size(); i++) {
158         result[i] = MallocCString(vec[i]);
159     }
160     return result;
161 }
162 
VectorToCArrInt32(const std::vector<int32_t> & vec)163 static int32_t* VectorToCArrInt32(const std::vector<int32_t>& vec)
164 {
165     int32_t* result = static_cast<int32_t*>(malloc(sizeof(int32_t) * vec.size()));
166     if (result == nullptr) {
167         LOGE("VectorToCArrInt32: malloc failed!");
168         return nullptr;
169     }
170     for (size_t i = 0; i < vec.size(); i++) {
171         result[i] = vec[i];
172     }
173     return result;
174 }
175 
VectorToCArrBool(const std::vector<bool> & vec)176 static bool* VectorToCArrBool(const std::vector<bool>& vec)
177 {
178     bool* result = static_cast<bool*>(malloc(sizeof(bool) * vec.size()));
179     if (result == nullptr) {
180         LOGE("VectorToCArrBool: malloc failed!");
181         return nullptr;
182     }
183     for (size_t i = 0; i < vec.size(); i++) {
184         result[i] = vec[i];
185     }
186     return result;
187 }
188 
VerifyAccessTokenSync(unsigned int tokenID,const char * cPermissionName)189 int32_t AtManagerImpl::VerifyAccessTokenSync(unsigned int tokenID, const char* cPermissionName)
190 {
191     LOGI("ACCESS_CTRL_TEST::AtManagerImpl::VerifyAccessTokenSync START");
192     static AccessTokenID selgTokenId = GetSelfTokenID();
193     if (tokenID != selgTokenId) {
194         auto result = AccessTokenKit::VerifyAccessToken(tokenID, cPermissionName);
195         LOGI("ACCESS_CTRL_TEST::AtManagerImpl::VerifyAccessTokenSync end.");
196         return result;
197     }
198 
199     int32_t result;
200     std::lock_guard<std::mutex> lock(g_lockCache);
201     auto iter = g_cache.find(cPermissionName);
202     if (iter != g_cache.end()) {
203         std::string currPara = GetPermParamValue();
204         if (currPara != iter->second.paramValue) {
205             result = AccessTokenKit::VerifyAccessToken(
206                 tokenID, cPermissionName);
207             iter->second.status = result;
208             iter->second.paramValue = currPara;
209             LOGI("Param changed currPara %{public}s", currPara.c_str());
210         } else {
211             result = iter->second.status;
212         }
213     } else {
214         result = AccessTokenKit::VerifyAccessToken(tokenID, cPermissionName);
215         g_cache[cPermissionName].status = result;
216         g_cache[cPermissionName].paramValue = GetPermParamValue();
217         LOGI("g_cacheParam set %{public}s", g_cache[cPermissionName].paramValue.c_str());
218     }
219     LOGI("ACCESS_CTRL_TEST::AtManagerImpl::VerifyAccessTokenSync end cache.");
220     return result;
221 }
222 
GrantUserGrantedPermission(unsigned int tokenID,const char * cPermissionName,unsigned int permissionFlags)223 int32_t AtManagerImpl::GrantUserGrantedPermission(unsigned int tokenID, const char* cPermissionName,
224     unsigned int permissionFlags)
225 {
226     LOGI("ACCESS_CTRL_TEST::AtManagerImpl::GrantUserGrantedPermission START");
227 
228     PermissionDef permissionDef;
229     permissionDef.grantMode = 0;
230     permissionDef.availableLevel = APL_NORMAL;
231     permissionDef.provisionEnable = false;
232     permissionDef.distributedSceneEnable = false;
233     permissionDef.labelId = 0;
234     permissionDef.descriptionId = 0;
235 
236     int32_t result = AccessTokenKit::GetDefPermission(cPermissionName, permissionDef);
237     if (result != AT_PERM_OPERA_SUCC) {
238         LOGE("ACCESS_CTRL_TEST::AtManagerImpl::GrantUserGrantedPermission failed");
239         return result;
240     }
241 
242     LOGI("permissionName = %{public}s, grantmode = %{public}d.",
243         cPermissionName, permissionDef.grantMode);
244 
245     // only user_grant permission can use innerkit class method to grant permission, system_grant return failed
246     if (permissionDef.grantMode == USER_GRANT) {
247         result = AccessTokenKit::GrantPermission(tokenID, cPermissionName, permissionFlags);
248     } else {
249         result = CjErrorCode::CJ_ERROR_PERMISSION_NOT_EXIST;
250     }
251     LOGI("tokenID = %{public}d, permissionName = %{public}s, flag = %{public}d, grant result = %{public}d.", tokenID,
252         cPermissionName, permissionFlags, result);
253     return result;
254 }
255 
RevokeUserGrantedPermission(unsigned int tokenID,const char * cPermissionName,unsigned int permissionFlags)256 int32_t AtManagerImpl::RevokeUserGrantedPermission(unsigned int tokenID, const char* cPermissionName,
257     unsigned int permissionFlags)
258 {
259     LOGI("ACCESS_CTRL_TEST::AtManagerImpl::RevokeUserGrantedPermission START");
260 
261     PermissionDef permissionDef;
262 
263     permissionDef.grantMode = 0;
264     permissionDef.availableLevel = APL_NORMAL;
265     permissionDef.provisionEnable = false;
266     permissionDef.distributedSceneEnable = false;
267     permissionDef.labelId = 0;
268     permissionDef.descriptionId = 0;
269 
270     int32_t result = AccessTokenKit::GetDefPermission(cPermissionName, permissionDef);
271     if (result != AT_PERM_OPERA_SUCC) {
272         LOGE("ACCESS_CTRL_TEST::AtManagerImpl::RevokeUserGrantedPermission failed");
273         return result;
274     }
275 
276     LOGI("permissionName = %{public}s, grantmode = %{public}d.", cPermissionName, permissionDef.grantMode);
277 
278     // only user_grant permission can use innerkit class method to grant permission, system_grant return failed
279     if (permissionDef.grantMode == USER_GRANT) {
280         result = AccessTokenKit::RevokePermission(tokenID, cPermissionName, permissionFlags);
281     } else {
282         result = CjErrorCode::CJ_ERROR_PERMISSION_NOT_EXIST;
283     }
284     LOGI("tokenID = %{public}d, permissionName = %{public}s, flag = %{public}d, revoke result = %{public}d.",
285         tokenID, cPermissionName, permissionFlags, result);
286     return result;
287 }
288 
RegisterPermStateChangeCallback(const char * cType,CArrUI32 cTokenIDList,CArrString cPermissionList,int64_t callbackRef)289 int32_t AtManagerImpl::RegisterPermStateChangeCallback(
290     const char* cType,
291     CArrUI32 cTokenIDList,
292     CArrString cPermissionList,
293     int64_t callbackRef)
294 {
295     RegisterPermStateChangeInfo* registerPermStateChangeInfo =
296         new (std::nothrow) RegisterPermStateChangeInfo();
297     if (registerPermStateChangeInfo == nullptr) {
298         LOGE("insufficient memory for subscribeCBInfo!");
299         return CJ_ERROR_OUT_OF_MEMORY;
300     }
301     std::unique_ptr<RegisterPermStateChangeInfo> callbackPtr {registerPermStateChangeInfo};
302     // ParseInputToRegister
303     auto ret = FillPermStateChangeInfo(cType, cTokenIDList, cPermissionList, callbackRef,
304         *registerPermStateChangeInfo);
305     if (ret != CJ_OK) {
306         LOGE("FillPermStateChangeInfo failed");
307         return ret;
308     }
309     if (IsExistRegister(registerPermStateChangeInfo)) {
310         LOGE("Subscribe failed. The current subscriber has been existed");
311         return CJ_ERROR_PARAM_INVALID;
312     }
313     int32_t result = AccessTokenKit::RegisterPermStateChangeCallback(registerPermStateChangeInfo->subscriber);
314     if (result != CJ_OK) {
315         LOGE("RegisterPermStateChangeCallback failed");
316         registerPermStateChangeInfo->errCode = result;
317         return GetCjErrorCode(result);
318     }
319     {
320         std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
321         g_permStateChangeRegisters.emplace_back(registerPermStateChangeInfo);
322         LOGE("add g_PermStateChangeRegisters.size = %{public}zu",
323             g_permStateChangeRegisters.size());
324     }
325     callbackPtr.release();
326     return result;
327 }
328 
UnregisterPermStateChangeCallback(const char * cType,CArrUI32 cTokenIDList,CArrString cPermissionList,int64_t callbackRef)329 int32_t AtManagerImpl::UnregisterPermStateChangeCallback(
330     const char* cType,
331     CArrUI32 cTokenIDList,
332     CArrString cPermissionList,
333     int64_t callbackRef)
334 {
335     UnregisterPermStateChangeInfo* unregisterPermStateChangeInfo =
336         new (std::nothrow) UnregisterPermStateChangeInfo();
337     if (unregisterPermStateChangeInfo == nullptr) {
338         LOGE("insufficient memory for subscribeCBInfo!");
339         return CJ_ERROR_OUT_OF_MEMORY;
340     }
341     std::unique_ptr<UnregisterPermStateChangeInfo> callbackPtr {unregisterPermStateChangeInfo};
342     // ParseInputToUnregister
343     auto ret = FillUnregisterPermStateChangeInfo(cType, cTokenIDList, cPermissionList, callbackRef,
344         *unregisterPermStateChangeInfo);
345     if (ret != CJ_OK) {
346         LOGE("FillPermStateChangeInfo failed");
347         return ret;
348     }
349     std::vector<RegisterPermStateChangeInfo*> batchPermStateChangeRegisters;
350 
351     if (!FindAndGetSubscriberInVector(unregisterPermStateChangeInfo, batchPermStateChangeRegisters)) {
352         LOGE("Unsubscribe failed. The current subscriber does not exist");
353         return CjErrorCode::CJ_ERROR_PARAM_INVALID;
354     }
355 
356     for (const auto& item : batchPermStateChangeRegisters) {
357         PermStateChangeScope scopeInfo;
358         item->subscriber->GetScope(scopeInfo);
359         int32_t result = AccessTokenKit::UnRegisterPermStateChangeCallback(item->subscriber);
360         if (result == RET_SUCCESS) {
361             DeleteRegisterFromVector(scopeInfo, item->callbackRef);
362         } else {
363             LOGE("Batch UnregisterPermActiveChangeCompleted failed");
364             return GetCjErrorCode(result);
365         }
366     }
367     return CJ_OK;
368 }
369 
fillRequestResult(CPermissionRequestResult & retData,std::vector<std::string> permissionList,std::vector<int32_t> permissionsState,std::vector<bool> dialogShownResults)370 static void fillRequestResult(CPermissionRequestResult& retData, std::vector<std::string> permissionList,
371     std::vector<int32_t> permissionsState, std::vector<bool> dialogShownResults)
372 {
373     retData.permissions.size = static_cast<int64_t>(permissionList.size());
374     retData.permissions.head = VectorToCArrString(permissionList);
375     if (retData.permissions.head == nullptr) {
376         return;
377     }
378     retData.authResults.size = static_cast<int64_t>(permissionsState.size());
379     retData.authResults.head = VectorToCArrInt32(permissionsState);
380 
381     retData.dialogShownResults.size = static_cast<int64_t>(dialogShownResults.size());
382     retData.dialogShownResults.head = VectorToCArrBool(dialogShownResults);
383 }
384 
UpdateGrantPermissionResultOnly(const std::vector<std::string> & permissions,const std::vector<int> & grantResults,const std::vector<int> & permissionsState,std::vector<int> & newGrantResults)385 static void UpdateGrantPermissionResultOnly(const std::vector<std::string>& permissions,
386     const std::vector<int>& grantResults, const std::vector<int>& permissionsState, std::vector<int>& newGrantResults)
387 {
388     uint32_t size = permissions.size();
389 
390     for (uint32_t i = 0; i < size; i++) {
391         int result = permissionsState[i] == DYNAMIC_OPER ? grantResults[i] : permissionsState[i];
392         newGrantResults.emplace_back(result);
393     }
394 }
395 
GrantResultsCallback(const std::vector<std::string> & permissions,const std::vector<int> & grantResults)396 void AuthorizationResult::GrantResultsCallback(const std::vector<std::string>& permissions,
397     const std::vector<int>& grantResults)
398 {
399     LOGI("AuthorizationResult::GrantResultsCallback");
400     RetDataCPermissionRequestResult ret{};
401     fillRequestResult(ret.data, permissions, grantResults, this->data_->dialogShownResults);
402     ret.code = AT_PERM_OPERA_SUCC;
403     data_->callbackRef(ret);
404 }
405 
StartServiceExtension(std::shared_ptr<RequestAsyncContext> & asyncContext)406 static int32_t StartServiceExtension(std::shared_ptr<RequestAsyncContext>& asyncContext)
407 {
408     sptr<IRemoteObject> remoteObject = new (std::nothrow) AuthorizationResult(asyncContext);
409     if (remoteObject == nullptr) {
410         return CjErrorCode::CJ_ERROR_INNER;
411     }
412 
413     AAFwk::Want want;
414     want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.grantServiceAbilityName);
415     want.SetParam(PERMISSION_KEY, asyncContext->permissionList);
416     want.SetParam(STATE_KEY, asyncContext->permissionsState);
417     want.SetParam(TOKEN_KEY, asyncContext->abilityContext->GetToken());
418     want.SetParam(CALLBACK_KEY, remoteObject);
419 
420     int32_t left;
421     int32_t top;
422     int32_t width;
423     int32_t height;
424     asyncContext->abilityContext->GetWindowRect(left, top, width, height);
425     want.SetParam(WINDOW_RECTANGLE_LEFT_KEY, left);
426     want.SetParam(WINDOW_RECTANGLE_TOP_KEY, top);
427     want.SetParam(WINDOW_RECTANGLE_WIDTH_KEY, width);
428     want.SetParam(WINDOW_RECTANGLE_HEIGHT_KEY, height);
429     want.SetParam(REQUEST_TOKEN_KEY, asyncContext->abilityContext->GetToken());
430     int32_t err = AAFwk::AbilityManagerClient::GetInstance()->RequestDialogService(
431         want, asyncContext->abilityContext->GetToken());
432     LOGI("End calling StartExtension. ret=%{public}d", err);
433     std::lock_guard<std::mutex> lock(g_lockForPermRequestCallbacks);
434     g_curRequestCode = (g_curRequestCode == INT_MAX) ? 0 : (g_curRequestCode + 1);
435     return err;
436 }
437 
ParseRequestPermissionFromUser(OHOS::AbilityRuntime::Context * context,CArrString cPermissionList,const std::function<void (RetDataCPermissionRequestResult)> & callbackRef,const std::shared_ptr<RequestAsyncContext> & asyncContext)438 bool AtManagerImpl::ParseRequestPermissionFromUser(OHOS::AbilityRuntime::Context* context, CArrString cPermissionList,
439     const std::function<void(RetDataCPermissionRequestResult)>& callbackRef,
440     const std::shared_ptr<RequestAsyncContext>& asyncContext)
441 {
442     // context : AbilityContext
443     auto contextSharedPtr = context->shared_from_this();
444     asyncContext->abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(contextSharedPtr);
445     if (asyncContext->abilityContext != nullptr) {
446         asyncContext->uiAbilityFlag = true;
447     } else {
448         LOGI("convert to ability context failed");
449         asyncContext->uiExtensionContext =
450             AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(contextSharedPtr);
451         if (asyncContext->uiExtensionContext == nullptr) {
452             LOGE("convert to ui extension context failed");
453             return false;
454         }
455     }
456     // permissionList
457     if (cPermissionList.size == 0) {
458         return false;
459     }
460     auto permissionList = CArrStringToVector(cPermissionList);
461     asyncContext->permissionList = permissionList;
462     asyncContext->callbackRef = callbackRef;
463     return true;
464 }
465 
ReleaseOrErrorHandle(int32_t code)466 void UIExtensionCallback::ReleaseOrErrorHandle(int32_t code)
467 {
468     Ace::UIContent* uiContent = nullptr;
469     if (this->reqContext_->uiAbilityFlag) {
470         uiContent = this->reqContext_->abilityContext->GetUIContent();
471     } else {
472         uiContent = this->reqContext_->uiExtensionContext->GetUIContent();
473     }
474     if (uiContent != nullptr) {
475         LOGI("close uiextension component");
476         uiContent->CloseModalUIExtension(this->sessionId_);
477     }
478 
479     if (code == 0) {
480         return; // code is 0 means request has return by OnResult
481     }
482 }
483 
UIExtensionCallback(const std::shared_ptr<RequestAsyncContext> & reqContext)484 UIExtensionCallback::UIExtensionCallback(const std::shared_ptr<RequestAsyncContext>& reqContext)
485 {
486     this->reqContext_ = reqContext;
487 }
488 
~UIExtensionCallback()489 UIExtensionCallback::~UIExtensionCallback()
490 {}
491 
SetSessionId(int32_t sessionId)492 void UIExtensionCallback::SetSessionId(int32_t sessionId)
493 {
494     this->sessionId_ = sessionId;
495 }
496 
497 /*
498  * when UIExtensionAbility disconnect or use terminate or process die
499  * releaseCode is 0 when process normal exit
500  */
OnRelease(int32_t releaseCode)501 void UIExtensionCallback::OnRelease(int32_t releaseCode)
502 {
503     LOGI("releaseCode is %{public}d", releaseCode);
504 
505     ReleaseOrErrorHandle(releaseCode);
506 }
507 
GrantResultsCallbackUI(const std::vector<std::string> & permissionList,const std::vector<int32_t> & permissionStates,std::shared_ptr<RequestAsyncContext> & data)508 static void GrantResultsCallbackUI(const std::vector<std::string>& permissionList,
509     const std::vector<int32_t>& permissionStates, std::shared_ptr<RequestAsyncContext>& data)
510 {
511     // only permissions which need to grant change the result, other keey as GetSelfPermissionsState result
512     std::vector<int> newGrantResults;
513     UpdateGrantPermissionResultOnly(permissionList, permissionStates, data->permissionsState, newGrantResults);
514     RetDataCPermissionRequestResult ret{};
515     fillRequestResult(ret.data, permissionList, newGrantResults, data->dialogShownResults);
516     ret.code = AT_PERM_OPERA_SUCC;
517     data->callbackRef(ret);
518 }
519 
520 /*
521  * when UIExtensionAbility use terminateSelfWithResult
522  */
OnResult(int32_t resultCode,const AAFwk::Want & result)523 void UIExtensionCallback::OnResult(int32_t resultCode, const AAFwk::Want& result)
524 {
525     LOGI("resultCode is %{public}d", resultCode);
526     std::vector<std::string> permissionList = result.GetStringArrayParam(PERMISSION_KEY);
527     std::vector<int32_t> permissionStates = result.GetIntArrayParam(RESULT_KEY);
528 
529     GrantResultsCallbackUI(permissionList, permissionStates, this->reqContext_);
530 }
531 
532 /*
533  * when UIExtensionAbility send message to UIExtensionComponent
534  */
OnReceive(const AAFwk::WantParams & receive)535 void UIExtensionCallback::OnReceive(const AAFwk::WantParams& receive)
536 {
537     LOGI("called!");
538 }
539 
540 /*
541  * when UIExtensionComponent init or turn to background or destroy UIExtensionAbility occur error
542  */
OnError(int32_t code,const std::string & name,const std::string & message)543 void UIExtensionCallback::OnError(int32_t code, const std::string& name, const std::string& message)
544 {
545     LOGI("code is %{public}d, name is %{public}s, message is %{public}s",
546         code, name.c_str(), message.c_str());
547 
548     ReleaseOrErrorHandle(code);
549 }
550 
551 /*
552  * when UIExtensionComponent connect to UIExtensionAbility, ModalUIExtensionProxy will init,
553  * UIExtensionComponent can send message to UIExtensionAbility by ModalUIExtensionProxy
554  */
OnRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy> & uiProxy)555 void UIExtensionCallback::OnRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy>& uiProxy)
556 {
557     LOGI("connect to UIExtensionAbility successfully.");
558 }
559 
560 /*
561  * when UIExtensionComponent destructed
562  */
OnDestroy()563 void UIExtensionCallback::OnDestroy()
564 {
565     LOGI("UIExtensionAbility destructed.");
566 }
567 
BindCallbacks(std::shared_ptr<UIExtensionCallback> uiExtCallback)568 static Ace::ModalUIExtensionCallbacks BindCallbacks(std::shared_ptr<UIExtensionCallback> uiExtCallback)
569 {
570     Ace::ModalUIExtensionCallbacks uiExtensionCallbacks = {
571         [uiExtCallback](int32_t releaseCode) {
572             uiExtCallback->OnRelease(releaseCode);
573         },
574         [uiExtCallback](int32_t resultCode, const OHOS::AAFwk::Want& result) {
575             uiExtCallback->OnResult(resultCode, result);
576         },
577         [uiExtCallback](const OHOS::AAFwk::WantParams& request) {
578             uiExtCallback->OnReceive(request);
579         },
580         [uiExtCallback](int32_t code, const std::string& name, [[maybe_unused]]const std::string& message) {
581             uiExtCallback->OnError(code, name, name);
582         },
583         [uiExtCallback](const std::shared_ptr<OHOS::Ace::ModalUIExtensionProxy>& uiProxy) {
584             uiExtCallback->OnRemoteReady(uiProxy);
585         },
586         [uiExtCallback] {
587             uiExtCallback->OnDestroy();
588         },
589     };
590     return uiExtensionCallbacks;
591 }
592 
CreateUIExtension(const Want & want,std::shared_ptr<RequestAsyncContext> asyncContext)593 static int32_t CreateUIExtension(const Want &want, std::shared_ptr<RequestAsyncContext> asyncContext)
594 {
595     Ace::UIContent* uiContent = nullptr;
596     int64_t beginTime = std::chrono::duration_cast<std::chrono::milliseconds>(
597         std::chrono::system_clock::now().time_since_epoch()).count();
598     if (asyncContext->uiAbilityFlag) {
599         while (true) {
600             uiContent = asyncContext->abilityContext->GetUIContent();
601             int64_t curTime = std::chrono::duration_cast<std::chrono::milliseconds>(
602                 std::chrono::system_clock::now().time_since_epoch()).count();
603             if ((uiContent != nullptr) || (curTime - beginTime > MAX_WAIT_TIME)) {
604                 break;
605             }
606         }
607     } else {
608         while (true) {
609             uiContent = asyncContext->uiExtensionContext->GetUIContent();
610             int64_t curTime = std::chrono::duration_cast<std::chrono::milliseconds>(
611                 std::chrono::system_clock::now().time_since_epoch()).count();
612             if ((uiContent != nullptr) || (curTime - beginTime > MAX_WAIT_TIME)) {
613                 break;
614             }
615         }
616     }
617 
618     if (uiContent == nullptr) {
619         LOGE("get ui content failed!");
620         asyncContext->result = CjErrorCode::CJ_ERROR_SYSTEM_CAPABILITY_NOT_SUPPORT;
621         return CjErrorCode::CJ_ERROR_SYSTEM_CAPABILITY_NOT_SUPPORT;
622     }
623     auto uiExtCallback = std::make_shared<UIExtensionCallback>(asyncContext);
624     auto uiExtensionCallbacks = BindCallbacks(uiExtCallback);
625     Ace::ModalUIExtensionConfig config;
626     config.isProhibitBack = true;
627     int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config);
628     if (sessionId == 0) {
629         asyncContext->result = CJ_ERROR_INNER;
630         return CJ_ERROR_INNER;
631     }
632     uiExtCallback->SetSessionId(sessionId);
633     return CJ_OK;
634 }
635 
StartUIExtension(std::shared_ptr<RequestAsyncContext> asyncContext)636 static int32_t StartUIExtension(std::shared_ptr<RequestAsyncContext> asyncContext)
637 {
638     AAFwk::Want want;
639     want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.grantAbilityName);
640     want.SetParam(PERMISSION_KEY, asyncContext->permissionList);
641     want.SetParam(STATE_KEY, asyncContext->permissionsState);
642     want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE);
643     return CreateUIExtension(want, asyncContext);
644 }
645 
RequestPermissionsFromUser(OHOS::AbilityRuntime::Context * context,CArrString cPermissionList,const std::function<void (RetDataCPermissionRequestResult)> & callbackRef)646 void AtManagerImpl::RequestPermissionsFromUser(OHOS::AbilityRuntime::Context* context, CArrString cPermissionList,
647     const std::function<void(RetDataCPermissionRequestResult)>& callbackRef)
648 {
649     RetDataCPermissionRequestResult ret = { .code = ERR_INVALID_INSTANCE_CODE,
650         .data = {
651             .permissions = { .head = nullptr, .size = 0 },
652             .authResults = { .head = nullptr, .size = 0 },
653             .dialogShownResults = { .head = nullptr, .size = 0 } } };
654     // use handle to protect asyncContext
655     std::shared_ptr<RequestAsyncContext> asyncContext = std::make_shared<RequestAsyncContext>();
656     if (!ParseRequestPermissionFromUser(context, cPermissionList, callbackRef, asyncContext)) {
657         ret.code = CjErrorCode::CJ_ERROR_PARAM_ILLEGAL;
658         callbackRef(ret);
659         return;
660     }
661     AccessTokenID tokenID = 0;
662     if (asyncContext->uiAbilityFlag) {
663         tokenID = asyncContext->abilityContext->GetApplicationInfo()->accessTokenId;
664     } else {
665         tokenID = asyncContext->uiExtensionContext->GetApplicationInfo()->accessTokenId;
666     }
667     if (tokenID != static_cast<AccessTokenID>(GetSelfTokenID())) {
668         ret.code = CjErrorCode::CJ_ERROR_PARAM_INVALID;
669         callbackRef(ret);
670         return;
671     }
672     if (!IsDynamicRequest(asyncContext->permissionList, asyncContext->permissionsState,
673         asyncContext->dialogShownResults, asyncContext->info)) {
674         fillRequestResult(ret.data, asyncContext->permissionList, asyncContext->permissionsState,
675             asyncContext->dialogShownResults);
676         ret.code = CJ_OK;
677         callbackRef(ret);
678         return;
679     }
680     int32_t result;
681     // service extension dialog
682     if (asyncContext->info.grantBundleName == GRANT_ABILITY_BUNDLE_NAME) {
683         LOGI("pop service extension dialog");
684         result = StartServiceExtension(asyncContext);
685     } else {
686         LOGI("pop ui extension dialog");
687         result = StartUIExtension(asyncContext);
688         if (result != CJ_OK) {
689             LOGI("pop uiextension dialog fail, start to pop service extension dialog");
690             result = StartServiceExtension(asyncContext);
691         }
692     }
693     ret.code = result;
694     if (ret.code != CJ_OK) {
695         callbackRef(ret);
696         return;
697     }
698 }
699 
FillPermStateChangeInfo(const std::string & type,CArrUI32 cTokenIDList,CArrString cPermissionList,int64_t callback,RegisterPermStateChangeInfo & registerPermStateChangeInfo)700 int32_t AtManagerImpl::FillPermStateChangeInfo(
701     const std::string& type,
702     CArrUI32 cTokenIDList,
703     CArrString cPermissionList,
704     int64_t callback,
705     RegisterPermStateChangeInfo& registerPermStateChangeInfo)
706 {
707     PermStateChangeScope scopeInfo;
708     // 1: ParseAccessTokenIDArray
709     for (int64_t i = 0; i < cTokenIDList.size; i++) {
710         uint32_t res = cTokenIDList.head[i];
711         scopeInfo.tokenIDs.emplace_back(res);
712     }
713     // 2: ParseStringArray
714     if (cPermissionList.size == 0) {
715         LOGE("array is empty");
716         return CJ_ERROR_PARAM_ILLEGAL;
717     }
718     for (int64_t i = 0; i < cPermissionList.size; i++) {
719         std::string str = cPermissionList.head[i];
720         scopeInfo.permList.emplace_back(str);
721     }
722     std::sort(scopeInfo.tokenIDs.begin(), scopeInfo.tokenIDs.end());
723     std::sort(scopeInfo.permList.begin(), scopeInfo.permList.end());
724     registerPermStateChangeInfo.callbackRef = callback;
725     registerPermStateChangeInfo.permStateChangeType = type;
726     registerPermStateChangeInfo.subscriber = std::make_shared<RegisterPermStateChangeScopePtr>(scopeInfo);
727     auto cFunc = reinterpret_cast<void(*)(CPermStateChangeInfo)>(callback);
728     registerPermStateChangeInfo.subscriber->SetCallbackRef(CJLambda::Create(cFunc));
729     registerPermStateChangeInfo.threadId = std::this_thread::get_id();
730     return CJ_OK;
731 }
732 
FillUnregisterPermStateChangeInfo(const std::string & type,CArrUI32 cTokenIDList,CArrString cPermissionList,int64_t callback,UnregisterPermStateChangeInfo & unregisterPermStateChangeInfo)733 int32_t AtManagerImpl::FillUnregisterPermStateChangeInfo(
734     const std::string& type,
735     CArrUI32 cTokenIDList,
736     CArrString cPermissionList,
737     int64_t callback,
738     UnregisterPermStateChangeInfo& unregisterPermStateChangeInfo)
739 {
740     PermStateChangeScope changeScopeInfo;
741     // 1: ParseAccessTokenIDArray
742     for (int i = 0; i < cTokenIDList.size; i++) {
743         uint32_t res = cTokenIDList.head[i];
744         changeScopeInfo.tokenIDs.emplace_back(res);
745     }
746     // 2: ParseStringArray
747     if (cPermissionList.size == 0) {
748         LOGE("array is empty");
749         return CJ_ERROR_PARAM_ILLEGAL;
750     }
751     for (int i = 0; i < cPermissionList.size; i++) {
752         std::string str = cPermissionList.head[i];
753         changeScopeInfo.permList.emplace_back(str);
754     }
755 
756     std::sort(changeScopeInfo.tokenIDs.begin(), changeScopeInfo.tokenIDs.end());
757     std::sort(changeScopeInfo.permList.begin(), changeScopeInfo.permList.end());
758     unregisterPermStateChangeInfo.callbackRef = callback;
759     unregisterPermStateChangeInfo.permStateChangeType = type;
760     unregisterPermStateChangeInfo.scopeInfo = changeScopeInfo;
761     unregisterPermStateChangeInfo.threadId = std::this_thread::get_id();
762     return CJ_OK;
763 }
764 
FindAndGetSubscriberInVector(UnregisterPermStateChangeInfo * unregisterPermStateChangeInfo,std::vector<RegisterPermStateChangeInfo * > & batchPermStateChangeRegisters)765 bool AtManagerImpl::FindAndGetSubscriberInVector(UnregisterPermStateChangeInfo* unregisterPermStateChangeInfo,
766     std::vector<RegisterPermStateChangeInfo*>& batchPermStateChangeRegisters)
767 {
768     std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
769     std::vector<AccessTokenID> targetTokenIDs = unregisterPermStateChangeInfo->scopeInfo.tokenIDs;
770     std::vector<std::string> targetPermList = unregisterPermStateChangeInfo->scopeInfo.permList;
771     for (const auto& item : g_permStateChangeRegisters) {
772         if (unregisterPermStateChangeInfo->callbackRef != 0) {
773             if (!CompareCallbackRef(item->callbackRef, unregisterPermStateChangeInfo->callbackRef, item->threadId)) {
774                 continue;
775             }
776         } else {
777             // batch delete currentThread callback
778             if (!IsCurrentThread(item->threadId)) {
779                 continue;
780             }
781         }
782         PermStateChangeScope scopeInfo;
783         item->subscriber->GetScope(scopeInfo);
784         if (scopeInfo.tokenIDs == targetTokenIDs && scopeInfo.permList == targetPermList) {
785             LOGI("find subscriber in map");
786             unregisterPermStateChangeInfo->subscriber = item->subscriber;
787             batchPermStateChangeRegisters.emplace_back(item);
788         }
789     }
790     if (!batchPermStateChangeRegisters.empty()) {
791         return true;
792     }
793     return false;
794 }
795 
DeleteRegisterFromVector(const PermStateChangeScope & scopeInfo,int64_t subscriberRef)796 void AtManagerImpl::DeleteRegisterFromVector(const PermStateChangeScope& scopeInfo, int64_t subscriberRef)
797 {
798     std::vector<AccessTokenID> targetTokenIDs = scopeInfo.tokenIDs;
799     std::vector<std::string> targetPermList = scopeInfo.permList;
800     std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
801     auto item = g_permStateChangeRegisters.begin();
802     while (item != g_permStateChangeRegisters.end()) {
803         PermStateChangeScope stateChangeScope;
804         (*item)->subscriber->GetScope(stateChangeScope);
805         if ((stateChangeScope.tokenIDs == targetTokenIDs) && (stateChangeScope.permList == targetPermList) &&
806             CompareCallbackRef((*item)->callbackRef, subscriberRef, (*item)->threadId)) {
807             LOGI("Find subscribers in vector, delete");
808             delete *item;
809             *item = nullptr;
810             g_permStateChangeRegisters.erase(item);
811             break;
812         } else {
813             ++item;
814         }
815     }
816 }
817 
GetPermParamValue()818 std::string AtManagerImpl::GetPermParamValue()
819 {
820     long long sysCommitId = GetSystemCommitId();
821     if (sysCommitId == g_paramCache.sysCommitIdCache) {
822         LOGI("sysCommitId = %{public}lld", sysCommitId);
823         return g_paramCache.sysParamCache;
824     }
825     g_paramCache.sysCommitIdCache = sysCommitId;
826     if (g_paramCache.handle == PARAM_DEFAULT_VALUE) {
827         int32_t handle = static_cast<int32_t>(FindParameter(PERMISSION_STATUS_CHANGE_KEY));
828         if (handle == PARAM_DEFAULT_VALUE) {
829             LOGE("FindParameter failed");
830             return "-1";
831         }
832         g_paramCache.handle = handle;
833     }
834 
835     int32_t currCommitId = static_cast<int32_t>(GetParameterCommitId(g_paramCache.handle));
836     if (currCommitId != g_paramCache.commitIdCache) {
837         char value[VALUE_MAX_LEN] = {0};
838         auto ret = GetParameterValue(g_paramCache.handle, value, VALUE_MAX_LEN - 1);
839         if (ret < 0) {
840             LOGE("return default value, ret=%{public}d", ret);
841             return "-1";
842         }
843         std::string resStr(value);
844         g_paramCache.sysParamCache = resStr;
845         g_paramCache.commitIdCache = currCommitId;
846     }
847     return g_paramCache.sysParamCache;
848 }
849 
IsExistRegister(const RegisterPermStateChangeInfo * registerPermStateChangeInfo)850 bool AtManagerImpl::IsExistRegister(const RegisterPermStateChangeInfo* registerPermStateChangeInfo)
851 {
852     PermStateChangeScope targetScopeInfo;
853     registerPermStateChangeInfo->subscriber->GetScope(targetScopeInfo);
854     std::vector<AccessTokenID> targetTokenIDs = targetScopeInfo.tokenIDs;
855     std::vector<std::string> targetPermList = targetScopeInfo.permList;
856     std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
857 
858     for (const auto& item : g_permStateChangeRegisters) {
859         PermStateChangeScope scopeInfo;
860         item->subscriber->GetScope(scopeInfo);
861 
862         bool hasPermIntersection = false;
863         // Special cases:
864         // 1.Have registered full, and then register some
865         // 2.Have registered some, then register full
866         if (scopeInfo.permList.empty() || targetPermList.empty()) {
867             hasPermIntersection = true;
868         }
869         for (const auto& PermItem : targetPermList) {
870             if (hasPermIntersection) {
871                 break;
872             }
873             auto iter = std::find(scopeInfo.permList.begin(), scopeInfo.permList.end(), PermItem);
874             if (iter != scopeInfo.permList.end()) {
875                 hasPermIntersection = true;
876             }
877         }
878 
879         bool hasTokenIdIntersection = false;
880 
881         if (scopeInfo.tokenIDs.empty() || targetTokenIDs.empty()) {
882             hasTokenIdIntersection = true;
883         }
884         for (const auto& tokenItem : targetTokenIDs) {
885             if (hasTokenIdIntersection) {
886                 break;
887             }
888             auto iter = std::find(scopeInfo.tokenIDs.begin(), scopeInfo.tokenIDs.end(), tokenItem);
889             if (iter != scopeInfo.tokenIDs.end()) {
890                 hasTokenIdIntersection = true;
891             }
892         }
893 
894         if (hasTokenIdIntersection && hasPermIntersection &&
895             CompareCallbackRef(item->callbackRef, registerPermStateChangeInfo->callbackRef, item->threadId)) {
896             return true;
897         }
898     }
899     LOGI("cannot find subscriber in vector");
900     return false;
901 }
902 
IsDynamicRequest(const std::vector<std::string> & permissions,std::vector<int32_t> & permissionsState,std::vector<bool> & dialogShownResults,PermissionGrantInfo & info)903 bool AtManagerImpl::IsDynamicRequest(const std::vector<std::string>& permissions,
904     std::vector<int32_t>& permissionsState, std::vector<bool>& dialogShownResults, PermissionGrantInfo& info)
905 {
906     std::vector<PermissionListState> permList;
907     for (const auto& permission : permissions) {
908         LOGI("permission: %{public}s.", permission.c_str());
909         PermissionListState permState;
910         permState.permissionName = permission;
911         permState.state = SETTING_OPER;
912         permList.emplace_back(permState);
913     }
914     LOGI("permList size: %{public}zu, permissions size: %{public}zu.",
915         permList.size(), permissions.size());
916 
917     auto ret = AccessTokenKit::GetSelfPermissionsState(permList, info);
918 
919     for (const auto& permState : permList) {
920         LOGI("permissions: %{public}s. permissionsState: %{public}u",
921             permState.permissionName.c_str(), permState.state);
922         permissionsState.emplace_back(permState.state);
923         dialogShownResults.emplace_back(permState.state == TypePermissionOper::DYNAMIC_OPER);
924     }
925     if (permList.size() != permissions.size()) {
926         LOGE("Returned permList size: %{public}zu.", permList.size());
927         return false;
928     }
929     if (ret != TypePermissionOper::DYNAMIC_OPER) {
930         return false;
931     }
932     return true;
933 }
934 
935 // PermStateChangeContext
~PermStateChangeContext()936 PermStateChangeContext::~PermStateChangeContext()
937 {}
938 
939 // RegisterPermStateChangeScopePtr
RegisterPermStateChangeScopePtr(const PermStateChangeScope & subscribeInfo)940 RegisterPermStateChangeScopePtr::RegisterPermStateChangeScopePtr(const PermStateChangeScope& subscribeInfo)
941     : PermStateChangeCallbackCustomize(subscribeInfo)
942 {}
943 
~RegisterPermStateChangeScopePtr()944 RegisterPermStateChangeScopePtr::~RegisterPermStateChangeScopePtr()
945 {}
946 
PermStateChangeCallback(PermStateChangeInfo & result)947 void RegisterPermStateChangeScopePtr::PermStateChangeCallback(PermStateChangeInfo& result)
948 {
949     std::lock_guard<std::mutex> lock(validMutex_);
950     if (!valid_) {
951         LOGE("object is invalid.");
952         return;
953     }
954     CPermStateChangeInfo info;
955     info.permStateChangeType = result.permStateChangeType;
956     info.tokenID = result.tokenID;
957     info.permissionName = MallocCString(result.permissionName);
958     ref_(info);
959 }
960 
SetCallbackRef(const std::function<void (CPermStateChangeInfo)> & ref)961 void RegisterPermStateChangeScopePtr::SetCallbackRef(const std::function<void(CPermStateChangeInfo)>& ref)
962 {
963     ref_ = ref;
964 }
965 
SetValid(bool valid)966 void RegisterPermStateChangeScopePtr::SetValid(bool valid)
967 {
968     std::lock_guard<std::mutex> lock(validMutex_);
969     valid_ = valid;
970 }
971 }
972 } // namespace CJSystemapi
973 } // namespace OHOS
974