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