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