1/* 2 * Copyright (c) 2021-2023 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 16import { backBar } from "../common/components/backBar"; 17import router from '@ohos.router'; 18import common from '@ohos.app.ability.common'; 19import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'; 20import bundleManager from '@ohos.bundle.bundleManager'; 21import { BusinessError } from '@ohos.base'; 22import { groups, userGrantPermissions } from "../common/model/permissionGroup"; 23import Constants from '../common/utils/constant'; 24import { verifyAccessToken, getGroupIdByPermission } from "../common/utils/utils"; 25import { permissionObj, appInfo } from '../common/utils/typedef'; 26import { GlobalContext } from '../common/utils/globalContext'; 27 28const TAG = 'PermissionManager_MainAbility:'; 29const FUZZY_LOCATION_PERMISSION = 'ohos.permission.APPROXIMATELY_LOCATION'; 30const PRECISE_LOCATION_PERMISSION = 'ohos.permission.LOCATION'; 31const allowedStatus = 0; // Status: Allowed 32const bannedStatus = 1; // Status: Banned 33 34@Entry 35@Component 36struct appNamePlusPage { 37 private context = getContext(this) as common.UIAbilityContext; 38 @State allowedListItem: permissionObj[] = []; // Array of allowed permissions 39 @State bannedListItem: permissionObj[] = []; // array of forbidden permissions 40 @State applicationInfo: appInfo = GlobalContext.load('applicationInfo'); // Routing jump data 41 @State bundleName: string = GlobalContext.load('bundleName'); 42 @State label: string = ''; 43 @State isTouch: string = ''; 44 45 @Builder ListItemLayout(item: permissionObj, status: number) { 46 ListItem() { 47 Row() { 48 Column() { 49 Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { 50 Row() { 51 Text(item.groupName) 52 .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE) 53 .fontColor($r('sys.color.ohos_id_color_text_primary')) 54 .fontWeight(FontWeight.Medium) 55 .flexGrow(Constants.FLEX_GROW) 56 Image($r('app.media.ic_public_arrow_right')) 57 .fillColor($r('sys.color.ohos_id_color_tertiary')) 58 .objectFit(ImageFit.Contain) 59 .height(Constants.IMAGE_HEIGHT) 60 .width(Constants.IMAGE_WIDTH) 61 } 62 .width(Constants.FULL_WIDTH) 63 .height(Constants.LISTITEM_ROW_HEIGHT) 64 } 65 }.onClick(() => { 66 GlobalContext.store('currentPermissionGroup', item.group); 67 router.pushUrl({ 68 url: item.group == "OTHER" ? 'pages/other-permissions' : 'pages/application-tertiary', 69 params: { 70 bundleName: this.applicationInfo.bundleName, 71 backTitle: item.groupName, 72 permission: item.permission, 73 status: !status ? allowedStatus : bannedStatus, 74 tokenId: this.applicationInfo.tokenId 75 } 76 }); 77 }) 78 } 79 }.padding({ left: $r('sys.float.ohos_id_card_margin_start'), right: $r('sys.float.ohos_id_card_margin_end') }) 80 .borderRadius($r("sys.float.ohos_id_corner_radius_default_l")) 81 .linearGradient((this.isTouch === item.group) ? { 82 angle: 90, 83 direction: GradientDirection.Right, 84 colors: [['#DCEAF9', 0.0], ['#FAFAFA', 1.0]] 85 } : { 86 angle: 90, 87 direction: GradientDirection.Right, 88 colors: [[$r("sys.color.ohos_id_color_list_card_bg"), 1], [$r("sys.color.ohos_id_color_list_card_bg"), 1]] 89 }) 90 .onTouch(event => { 91 if (event === undefined) { 92 return; 93 } 94 if (event.type === TouchType.Down) { 95 this.isTouch = item.group; 96 } 97 if (event.type === TouchType.Up) { 98 this.isTouch = ''; 99 } 100 }) 101 } 102 103 async initApplicationInfo(info: appInfo) { 104 console.info(TAG + `labelId: ` + JSON.stringify(info.labelId)); 105 let resourceManager = this.context.createBundleContext(info.bundleName).resourceManager; 106 107 resourceManager.getStringValue(info.labelId, (error, value) => { 108 info.label = value; 109 }) 110 111 try { 112 let iconDescriptor = resourceManager.getDrawableDescriptor(info.iconId); 113 info.icon = iconDescriptor?.getPixelMap(); 114 } catch (error) { 115 console.error(`getDrawableDescriptor failed, error code: ${error.code}, message: ${error.message}.`); 116 } 117 let icon = info.icon; 118 if (!icon) { 119 info.icon = await resourceManager.getMediaContentBase64(info.iconId); 120 } 121 let icon1 = info.icon; 122 if (!icon1) { 123 info.icon = $r('app.media.icon'); 124 } 125 126 let reqUserPermissions: Permissions[] = []; 127 let acManager = abilityAccessCtrl.createAtManager(); 128 if (info.permissions.length > 0) { 129 for (let j = 0; j < info.permissions.length; j++) { 130 let permission = info.permissions[j]; 131 if (userGrantPermissions.indexOf(permission) == -1) { 132 continue; 133 } 134 if ((info.api < Constants.API_VERSION_SUPPORT_STAGE) && (permission == FUZZY_LOCATION_PERMISSION)) { 135 continue; 136 } 137 try { 138 let flag = await acManager.getPermissionFlags(info.tokenId, permission); 139 if (flag == Constants.PERMISSION_SYSTEM_FIXED) { 140 continue; 141 } 142 } 143 catch(err) { 144 console.log(TAG + 'getPermissionFlags error: ' + JSON.stringify(err)); 145 } 146 reqUserPermissions.push(permission); 147 } 148 } 149 let groupIds: number[] = []; 150 for (let i = 0; i < reqUserPermissions.length; i++) { 151 let groupId = getGroupIdByPermission(reqUserPermissions[i]) 152 if (groupIds.indexOf(groupId) == -1) { 153 groupIds.push(groupId); 154 } 155 } 156 info.permissions = reqUserPermissions; 157 info.groupId = groupIds; 158 } 159 160 /** 161 * Initialize permission status information and group permission information 162 */ 163 async initialPermissions() { 164 if (this.bundleName && !this.applicationInfo.groupId.length) { 165 await this.initApplicationInfo(this.applicationInfo); 166 } 167 let reqPermissions = this.applicationInfo.permissions; 168 let reqGroupIds = this.applicationInfo.groupId; 169 170 this.allowedListItem = []; 171 this.bannedListItem = []; 172 173 for (let i = 0; i < reqGroupIds.length; i++) { 174 let id = reqGroupIds[i]; 175 let groupName = groups[id].groupName; 176 let group = groups[id].name; 177 let groupReqPermissons: Permissions[] = []; 178 for (let j = 0; j < reqPermissions.length; j++) { 179 let permission = reqPermissions[j]; 180 if (groups[id].permissions.indexOf(permission) != -1) { 181 groupReqPermissons.push(permission); 182 } 183 } 184 let isGranted = true; 185 for (let i = 0; i < groupReqPermissons.length; i++) { 186 let permission = groupReqPermissons[i]; 187 if (this.applicationInfo.api >= Constants.API_VERSION_SUPPORT_STAGE && permission == PRECISE_LOCATION_PERMISSION) { 188 continue; 189 } 190 let res = await verifyAccessToken(this.applicationInfo.tokenId, permission); 191 if (res != abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) { 192 isGranted = false; 193 } 194 } 195 196 if (isGranted) { 197 this.allowedListItem.push(new permissionObj(groupName, groupReqPermissons, group)); 198 } else { 199 this.bannedListItem.push(new permissionObj(groupName, groupReqPermissons, group)); 200 } 201 } 202 } 203 204 /** 205 * Lifecycle function, triggered once when this page is displayed 206 */ 207 onPageShow() { 208 console.log(TAG + 'onPageShow application-secondary'); 209 this.initialPermissions(); 210 bundleManager.getApplicationInfo(this.applicationInfo.bundleName, bundleManager.ApplicationFlag.GET_APPLICATION_INFO_DEFAULT).then(appInfo => { 211 let bundleContext = this.context.createBundleContext(this.applicationInfo.bundleName) 212 bundleContext.resourceManager.getStringValue(appInfo.labelId, (error, value) => { 213 if (value) { 214 this.applicationInfo.label = value; 215 GlobalContext.store('applicationInfo', this.applicationInfo); 216 this.label = value 217 } 218 }) 219 }).catch((error: BusinessError) => { 220 console.error(TAG + 'getApplicationInfo error: ' + JSON.stringify(error)); 221 }) 222 } 223 224 build() { 225 Column(){ 226 GridRow({ gutter: Constants.GUTTER, columns: { 227 xs: Constants.XS_COLUMNS, sm: Constants.SM_COLUMNS, md: Constants.MD_COLUMNS, lg: Constants.LG_COLUMNS } }) { 228 GridCol({ span: { xs: Constants.XS_SPAN, sm: Constants.SM_SPAN, md: Constants.MD_SPAN, lg: Constants.LG_SPAN }, 229 offset: { xs: Constants.XS_OFFSET, sm: Constants.SM_OFFSET, md: Constants.MD_OFFSET, lg: Constants.LG_OFFSET } }) { 230 Row() { 231 Column() { 232 Row() { 233 backBar({ title: JSON.stringify(this.label || this.applicationInfo.label), recordable: false }) 234 } 235 Row() { 236 Column() { 237 if (!this.allowedListItem.length && !this.bannedListItem.length) { 238 Row() { 239 List() { 240 ListItem() { 241 Row() { 242 Column() { 243 Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { 244 Row() { 245 Column() { 246 Row() { 247 Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { 248 Text($r('app.string.no_permission')) 249 .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE) 250 .fontColor($r('sys.color.ohos_id_color_text_primary')) 251 }.margin({ top: Constants.FLEX_MARGIN_TOP, bottom: Constants.FLEX_MARGIN_BOTTOM }) 252 }.height(Constants.FULL_HEIGHT) 253 }.flexGrow(Constants.FLEX_GROW) 254 .constraintSize({minHeight: Constants.CONSTRAINTSIZE_MINHEIGHT }) 255 } 256 .width(Constants.FULL_WIDTH) 257 .height(Constants.LISTITEM_ROW_HEIGHT) 258 } 259 } 260 } 261 }.padding({ left: Constants.LISTITEM_PADDING_LEFT, right: Constants.LISTITEM_PADDING_RIGHT }) 262 } 263 .backgroundColor($r('sys.color.ohos_id_color_list_card_bg')) 264 .borderRadius($r('sys.float.ohos_id_corner_radius_card')) 265 .padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM }) 266 }.margin({ top: Constants.ROW_MARGIN_TOP }) 267 .padding({ left: Constants.SECONDARY_LIST_PADDING_LEFT, right: Constants.SECONDARY_LIST_PADDING_RIGHT }) 268 } else { 269 Scroll() { 270 List() { 271 if (this.allowedListItem.length) { 272 ListItem() { 273 Row() { 274 Text($r('app.string.allowed')) 275 .fontSize(Constants.TEXT_SMALL_FONT_SIZE) 276 .fontColor($r('sys.color.ohos_id_color_text_secondary')) 277 .fontWeight(FontWeight.Medium) 278 .lineHeight(Constants.SUBTITLE_LINE_HEIGHT) 279 }.constraintSize({ minHeight: Constants.SUBTITLE_MIN_HEIGHT }) 280 .width(Constants.FULL_WIDTH) 281 .padding({ top: Constants.SUBTITLE_PADDING_TOP, bottom: Constants.SUBTITLE_PADDING_BOTTOM, 282 left: Constants.SECONDARY_TEXT_MARGIN_LEFT}) 283 } 284 285 ListItem() { 286 Row() { 287 List() { 288 ForEach(this.allowedListItem, (item: permissionObj) => { 289 this.ListItemLayout(item, Constants.RADIO_ALLOW_INDEX) 290 }, (item: permissionObj) => JSON.stringify(item)) 291 } 292 .backgroundColor($r('sys.color.ohos_id_color_list_card_bg')) 293 .borderRadius($r('sys.float.ohos_id_corner_radius_card')) 294 .padding(Constants.LIST_PADDING_TOP) 295 .divider({ 296 strokeWidth: Constants.DIVIDER, 297 color: $r('sys.color.ohos_id_color_list_separator'), 298 startMargin: Constants.DEFAULT_MARGIN_START, 299 endMargin: Constants.DEFAULT_MARGIN_END 300 }) 301 }.margin({ top: Constants.ROW_MARGIN_TOP }) 302 .padding({ 303 left: Constants.SECONDARY_LIST_PADDING_LEFT, 304 right: Constants.SECONDARY_LIST_PADDING_RIGHT 305 }) 306 } 307 } 308 if (this.bannedListItem.length) { 309 ListItem() { 310 Row() { 311 Text($r('app.string.banned')) 312 .fontSize(Constants.TEXT_SMALL_FONT_SIZE) 313 .fontColor($r('sys.color.ohos_id_color_text_secondary')) 314 .fontWeight(FontWeight.Medium) 315 .lineHeight(Constants.SUBTITLE_LINE_HEIGHT) 316 }.constraintSize({ minHeight: Constants.SUBTITLE_MIN_HEIGHT }) 317 .width(Constants.FULL_WIDTH) 318 .padding({ top: Constants.SUBTITLE_PADDING_TOP, bottom: Constants.SUBTITLE_PADDING_BOTTOM, 319 left: Constants.SECONDARY_TEXT_MARGIN_LEFT}) 320 } 321 322 ListItem() { 323 Row() { 324 List() { 325 ForEach(this.bannedListItem, (item: permissionObj) => { 326 this.ListItemLayout(item, Constants.RADIO_BAN_INDEX) 327 }, (item: permissionObj) => JSON.stringify(item)) 328 } 329 .backgroundColor($r('sys.color.ohos_id_color_list_card_bg')) 330 .borderRadius($r('sys.float.ohos_id_corner_radius_card')) 331 .padding(Constants.LIST_PADDING_TOP) 332 .divider({ 333 strokeWidth: Constants.DIVIDER, 334 color: $r('sys.color.ohos_id_color_list_separator'), 335 startMargin: Constants.DEFAULT_MARGIN_START, 336 endMargin: Constants.DEFAULT_MARGIN_END 337 }) 338 }.margin({ top: Constants.ROW_MARGIN_TOP }) 339 .padding({ 340 left: Constants.SECONDARY_LIST_PADDING_LEFT, 341 right: Constants.SECONDARY_LIST_PADDING_RIGHT 342 }) 343 } 344 } 345 } 346 }.scrollBar(BarState.Off) 347 } 348 } 349 .width(Constants.FULL_WIDTH) 350 .height(Constants.FULL_HEIGHT) 351 } 352 .layoutWeight(Constants.LAYOUT_WEIGHT) 353 } 354 } 355 .height(Constants.FULL_HEIGHT) 356 .width(Constants.FULL_WIDTH) 357 .backgroundColor($r("sys.color.ohos_id_color_sub_background")) 358 } 359 }.backgroundColor($r("sys.color.ohos_id_color_sub_background")) 360 } 361 } 362} 363