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