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