1/* 2 * Copyright (c) 2021-2022 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 bundle from "@ohos.bundle"; 19import bundleManager from '@ohos.bundle.bundleManager'; 20import { getAppLabel, getAppIcon } from "../common/utils/utils"; 21import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; 22import { authorizeDialog } from "../common/components/dialog"; 23import { showSubpermissionsGrop } from "../common/model/permissionGroup"; 24import Constants from '../common/utils/constant'; 25 26var TAG = 'PermissionManager_MainAbility:' 27 28let routerData: any = router.getParams()['routerData']; // Routing jump data 29let backTitle: any = router.getParams()['backTitle']; // return title name 30let status = router.getParams()['status']; // Status: Allowed, Forbidden 31let permissions: any = router.getParams()['permission']; // permissions name 32let nowGrantResult = Constants.PERMISSION_NUM; // Authorization results now 33let nowRevokeResult = Constants.PERMISSION_NUM; // Now deauthorize results 34let GrantResultFlag = []; // Authorization result Flag 35let RevokeResultFlag = []; // Cancel authorization result Flag 36let reason = null // Authorized reason 37let bundleInfo: any = {} 38const PRECISE_LOCATION_PERMISSION = 'ohos.permission.LOCATION' 39class MeidaDocObj { 40 name: Resource 41 index: number 42 groupName: string 43 accessTokenId: number 44 permissions: [] 45 constructor( 46 name: Resource, 47 index: number, 48 groupName: string, 49 accessTokenId: number, 50 permissions: [] 51 ) { 52 this.name = name 53 this.index = index 54 this.groupName = groupName 55 this.accessTokenId = accessTokenId 56 this.permissions = permissions 57 } 58}; // permission information class 59class MediaListObj { 60 labelId: string 61 iconId: string 62 versionName: string 63 constructor(labelId: string, iconId: string, versionName: string,) { 64 this.labelId = labelId 65 this.iconId = iconId 66 this.versionName = versionName 67 } 68}; // Permission application information class 69 70class ResourceObj { 71 period: string 72 comma: string 73 constructor(period: string, comma: string) { 74 this.period = period 75 this.comma = comma 76 } 77} 78 79@Entry 80@Component 81struct mediaDocumentPage { 82 build() { 83 Column() { 84 GridContainer({ gutter: Constants.GUTTER, margin: Constants.GRID_MARGIN }) { 85 Row() { 86 Row() 87 .useSizeType({ 88 xs: { span: Constants.LEFT_XS_SPAN, offset: Constants.LEFT_XS_OFFSET }, 89 sm: { span: Constants.LEFT_SM_SPAN, offset: Constants.LEFT_SM_OFFSET }, 90 md: { span: Constants.LEFT_MD_SPAN, offset: Constants.LEFT_MD_OFFSET }, 91 lg: { span: Constants.LEFT_LG_SPAN, offset: Constants.LEFT_LG_OFFSET } 92 }) 93 .height(Constants.FULL_HEIGHT) 94 Row() { 95 Column() { 96 Row() { 97 backBar({ title: JSON.stringify(backTitle), recordable: false }) 98 } 99 Row() { 100 Column() { 101 mediaDocumentItem() 102 }.width(Constants.FULL_WIDTH) 103 } 104 .margin({ top: Constants.TITLE_MARGIN_BOTTOM }) 105 .layoutWeight(Constants.LAYOUT_WEIGHT) 106 } 107 } 108 .useSizeType({ 109 xs: { span: Constants.MIDDLE_XS_SPAN, offset: Constants.MIDDLE_XS_OFFSET }, 110 sm: { span: Constants.MIDDLE_SM_SPAN, offset: Constants.MIDDLE_SM_OFFSET }, 111 md: { span: Constants.MIDDLE_MD_SPAN, offset: Constants.MIDDLE_MD_OFFSET }, 112 lg: { span: Constants.MIDDLE_LG_SPAN, offset: Constants.MIDDLE_LG_OFFSET } 113 }) 114 .height(Constants.FULL_HEIGHT) 115 Row() 116 .useSizeType({ 117 xs: { span: Constants.RIGHT_XS_SPAN, offset: Constants.RIGHT_XS_OFFSET }, 118 sm: { span: Constants.RIGHT_SM_SPAN, offset: Constants.RIGHT_SM_OFFSET }, 119 md: { span: Constants.RIGHT_MD_SPAN, offset: Constants.RIGHT_MD_OFFSET }, 120 lg: { span: Constants.RIGHT_LG_SPAN, offset: Constants.RIGHT_LG_OFFSET } 121 }) 122 .height(Constants.FULL_HEIGHT) 123 } 124 .height(Constants.FULL_HEIGHT) 125 .width(Constants.FULL_WIDTH) 126 .backgroundColor($r("sys.color.ohos_id_color_sub_background")) 127 } 128 } 129 } 130} 131 132@Component 133struct mediaDocumentItem { 134 @State mediaDocListItem: MeidaDocObj[] = []; // Permission information array 135 @State mediaListItem: MediaListObj = { 136 labelId: '', 137 iconId: '', 138 versionName: '', 139 }; // application info array 140 @State isCheckList: boolean[] = []; // Permission status array 141 @State accurateIsOn: boolean = true; 142 @State api: number = 0; 143 @State resource: ResourceObj = new ResourceObj('', '') 144 145 authorizeDialogController: CustomDialogController = new CustomDialogController({ 146 builder: authorizeDialog({ }), 147 autoCancel: true, 148 alignment: DialogAlignment.Center 149 }); 150 151 /** 152 * Grant permissions to the app 153 * @param {Number} accessTokenId 154 * @param {String} permission permission name 155 */ 156 grantUserGrantedPermission(accessTokenId, permission) { 157 abilityAccessCtrl.createAtManager().grantUserGrantedPermission( 158 accessTokenId, permission, Constants.PERMISSION_FLAG).then(() => { 159 nowGrantResult = Constants.PERMISSION_INDEX; 160 }) 161 .catch((error) => { 162 console.error(TAG + 'grantUserGrantedPermission failed. Cause: ' + JSON.stringify(error)); 163 }) 164 } 165 166 /** 167 * Deauthorize the app 168 * @param {Number} accessTokenId 169 * @param {String} permission permission name 170 */ 171 revokeUserGrantedPermission(accessTokenId, permission) { 172 abilityAccessCtrl.createAtManager().revokeUserGrantedPermission( 173 accessTokenId, permission, Constants.PERMISSION_FLAG).then(() => { 174 nowRevokeResult = Constants.PERMISSION_INDEX; 175 }) 176 .catch((error) => { 177 console.error(TAG + 'revokeUserGrantedPermission failed. Cause: ' + JSON.stringify(error)); 178 }) 179 } 180 181 /** 182 * Lifecycle function, executed when the page is initialized 183 */ 184 aboutToAppear() { 185 if(showSubpermissionsGrop.indexOf(globalThis.currentPermissionGroup) != -1) { 186 reason = [] 187 permissions.forEach(permission => { 188 reason.push(globalThis.permissionLabels[permission]) 189 }) 190 Promise.all([globalThis.context.resourceManager.getString($r("app.string.separator").id), 191 globalThis.context.resourceManager.getString($r("app.string.reason_suffix").id), 192 globalThis.context.resourceManager.getString($r("app.string.and").id), 193 globalThis.context.resourceManager.getString($r("app.string.period").id), 194 globalThis.context.resourceManager.getString($r("app.string.comma").id)]) 195 .then(values => { 196 this.resource.period = values[3] 197 this.resource.comma = values[4] 198 reason = globalThis.currentPermissionGroup == 'SMS' ? (reason.join(values[0]) + values[1]) : (reason.join(values[2]) + values[3]) 199 }) 200 }else { 201 reason = '' 202 } 203 let hasReason = false 204 bundleManager.getBundleInfo(routerData, Constants.PARMETER_BUNDLE_FLAG).then(info => { 205 permissions.forEach(permission => { 206 info.reqPermissionDetails.forEach(reqPermissionDetail => { 207 if(reqPermissionDetail.name == permission) { 208 let context = globalThis.context.createBundleContext(routerData) 209 context.resourceManager.getString(reqPermissionDetail.reasonId).then(value => { 210 if (value !== undefined && !hasReason) { 211 reason = reason.replace(this.resource.period, this.resource.comma) 212 reason += value.slice(Constants.START_SUBSCRIPT, Constants.END_SUBSCRIPT) 213 hasReason = true 214 } 215 }) 216 } 217 }) 218 }) 219 }) 220 bundle.getBundleInfo(routerData, Constants.PARMETER_BUNDLE_FLAG).then(res => { 221 this.api = res.targetVersion 222 bundleInfo = res 223 var acManager = abilityAccessCtrl.createAtManager() 224 acManager.verifyAccessToken(res.appInfo.accessTokenId, PRECISE_LOCATION_PERMISSION).then(accurateStatus => { 225 accurateStatus == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED ? this.accurateIsOn = true : this.accurateIsOn = false 226 }) 227 Promise.all([getAppLabel(res.appInfo.labelId, res.name), 228 getAppIcon(res.appInfo.iconId, res.name)]) 229 .then((values) => { 230 this.mediaListItem = new MediaListObj( 231 String(values[0]), String(values[1]), res.versionName); 232 }) 233 this.mediaDocListItem.push( 234 new MeidaDocObj( 235 $r('app.string.allow'), 236 Constants.RADIO_ALLOW_INDEX, 237 Constants.RADIO_ALLOW_GROUP_NAME, 238 res.appInfo.accessTokenId, 239 permissions 240 ) 241 ); 242 this.mediaDocListItem.push( 243 new MeidaDocObj( 244 $r('app.string.ban'), 245 Constants.RADIO_BAN_INDEX, 246 Constants.RADIO_BAN_GROUP_NAME, 247 res.appInfo.accessTokenId, 248 permissions 249 ) 250 ); 251 }).catch((error) => { 252 console.error(TAG + 'bundle.getBundleInfo failed. Cause: ' + JSON.stringify(error)); 253 this.mediaListItem = new MediaListObj('', '', ''); 254 this.mediaDocListItem.push( 255 new MeidaDocObj($r('app.string.allow'), Constants.RADIO_ALLOW_INDEX, 256 Constants.RADIO_ALLOW_GROUP_NAME, 0, permissions) 257 ); 258 this.mediaDocListItem.push( 259 new MeidaDocObj($r('app.string.ban'), Constants.RADIO_BAN_INDEX, 260 Constants.RADIO_BAN_GROUP_NAME, 0, permissions) 261 ); 262 }) 263 // Get permission status 264 if (!status) { 265 this.isCheckList = [true, false]; 266 } else { 267 this.isCheckList = [false, true]; 268 } 269 } 270 271 build(){ 272 Column() { 273 Row() { 274 Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { 275 Image(this.mediaListItem.iconId) 276 .width(Constants.TERTIARY_IMAGE_WIDTH) 277 .height(Constants.TERTIARY_IMAGE_HEIGHT) 278 .margin({ left: Constants.TERTIARY_IMAGE_MARGIN_LEFT, right: Constants.TERTIARY_IMAGE_MARGIN_RIGHT }) 279 Column() { 280 Row() { 281 Text(this.mediaListItem.labelId) 282 .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE) 283 .fontColor($r('app.color.label_color')) 284 .fontWeight(FontWeight.Bold) 285 .textAlign(TextAlign.Start) 286 } 287 .width(Constants.TERTIARY_HALF_WIDTH) 288 .margin({ bottom: Constants.TERTIARY_LABEL_MARGIN_BOTTOM }) 289 Row() { 290 Text(this.mediaListItem.versionName) 291 .fontSize(Constants.TEXT_SMAL_FONT_SIZE) 292 .fontColor($r('app.color.label_color_light')) 293 .textAlign(TextAlign.Start) 294 } 295 .width(Constants.TERTIARY_HALF_WIDTH) 296 } 297 }.margin({ left: Constants.TERTIARY_MARGIN_LEFT }) 298 } 299 if(reason) { 300 Row() { 301 Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { 302 Row() { 303 Text(reason) 304 .fontSize(Constants.TEXT_SMAL_FONT_SIZE) 305 .fontColor($r('app.color.label_color_light')) 306 .textAlign(TextAlign.Start) 307 }.margin({ left: Constants.TERTIARY_IMAGE_MARGIN_LEFT, right: Constants.TERTIARY_IMAGE_MARGIN_RIGHT }) 308 } 309 } 310 .margin({ top: Constants.TERTIARY_ROW_MARGIN_TOP, left: Constants.TERTIARY_MARGIN_LEFT }) 311 } 312 Row() { 313 Text(backTitle) 314 .fontSize(Constants.TEXT_SMAL_FONT_SIZE) 315 .fontColor($r('app.color.label_color_light')) 316 .fontWeight(FontWeight.Medium) 317 .textAlign(TextAlign.Start) 318 .lineHeight(Constants.SUBTITLE_LINE_HEIGHT) 319 Text($r('app.string.access_permission')) 320 .fontSize(Constants.TEXT_SMAL_FONT_SIZE) 321 .fontColor($r('app.color.label_color_light')) 322 .fontWeight(FontWeight.Medium) 323 .textAlign(TextAlign.Start) 324 .lineHeight(Constants.SUBTITLE_LINE_HEIGHT) 325 }.width(Constants.FULL_WIDTH) 326 .constraintSize({ minHeight: Constants.SUBTITLE_MIN_HEIGHT }) 327 .padding({ top: Constants.SUBTITLE_PADDING_TOP, bottom: Constants.SUBTITLE_PADDING_BOTTOM, 328 left: Constants.TERTIARY_TEXT_MARGIN_LEFT, right: Constants.TERTIARY_IMAGE_MARGIN_RIGHT}) 329 .margin({ top: Constants.TERTIARY_PERMISSION_ROW_MARGIN_TOP }) 330 Column() { 331 List() { 332 ForEach(this.mediaDocListItem, (item) => { 333 ListItem() { 334 Column() { 335 Row() { 336 Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { 337 Row() { 338 Text(item.name) 339 .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE) 340 .fontColor($r('app.color.label_color')) 341 .fontWeight(FontWeight.Medium) 342 .flexGrow(Constants.FLEX_GROW) 343 if (this.isCheckList[item.index] === true) { 344 Shape() { 345 Circle().width(Constants.SHAPE_DIA).height(Constants.SHAPE_DIA) 346 .fill($r("app.color.shape_allow_color")).offset({ x: 0, y: 0 }) 347 Circle().width(Constants.SHAPE_ALLOW_DIA).height(Constants.SHAPE_ALLOW_DIA) 348 .fill($r("app.color.default_background_color")) 349 .offset({ x: Constants.SHAPE_ALLOW_OFFSET, y: Constants.SHAPE_ALLOW_OFFSET }) 350 } 351 } else if (this.isCheckList[item.index] === false) { 352 Shape() { 353 Circle().width(Constants.SHAPE_DIA).height(Constants.SHAPE_DIA) 354 .fill($r("app.color.shape_ban_color")).offset({ x: 0, y: 0 }) 355 Circle().width(Constants.SHAPE_BAN_DIA).height(Constants.SHAPE_BAN_DIA) 356 .fill($r("app.color.default_background_color")) 357 .offset({ x: Constants.SHAPE_BAN_OFFSET, y: Constants.SHAPE_BAN_OFFSET }) 358 } 359 } 360 } 361 .width(Constants.FULL_WIDTH) 362 .height(Constants.LISTITEM_ROW_HEIGHT) 363 .onClick(() => { 364 item.permissions.forEach((permission) => { 365 if (!item.index) { 366 if((this.api >= Constants.API_VERSION_SUPPORT_STAGE) && (permission == PRECISE_LOCATION_PERMISSION)) { 367 return false 368 } 369 this.grantUserGrantedPermission(item.accessTokenId, permission) 370 if (nowGrantResult != Constants.PERMISSION_INDEX) { 371 GrantResultFlag.push(-1) 372 }else{ 373 GrantResultFlag.push(0) 374 } 375 } else { 376 if((permission == PRECISE_LOCATION_PERMISSION) && (this.api >= Constants.API_VERSION_SUPPORT_STAGE)) { 377 if(this.accurateIsOn) { 378 this.revokeUserGrantedPermission(item.accessTokenId, permission) 379 this.accurateIsOn = false 380 } 381 }else { 382 this.revokeUserGrantedPermission(item.accessTokenId, permission) 383 } 384 385 if (nowRevokeResult != Constants.PERMISSION_INDEX) { 386 RevokeResultFlag.push(-1) 387 this.authorizeDialogController.open(); 388 setTimeout(()=> { 389 this.authorizeDialogController.close(); 390 }, Constants.DELAY_TIME) 391 }else{ 392 RevokeResultFlag.push(0) 393 } 394 } 395 }) 396 if (!item.index) { 397 if(GrantResultFlag.indexOf(-1) > -1){ 398 this.authorizeDialogController.open(); 399 setTimeout(()=> { 400 this.authorizeDialogController.close(); 401 }, Constants.DELAY_TIME) 402 }else{ 403 this.isCheckList = [true, false]; 404 } 405 }else{ 406 if (RevokeResultFlag.indexOf(-1) > -1){ 407 this.authorizeDialogController.open(); 408 setTimeout(()=> { 409 this.authorizeDialogController.close(); 410 }, Constants.DELAY_TIME) 411 }else{ 412 this.isCheckList = [false, true]; 413 } 414 } 415 }) 416 } 417 } 418 if (!item.index) { 419 Row() { 420 Column() 421 .backgroundColor($r('app.color.text_decoration_color')) 422 .width(Constants.FULL_WIDTH) 423 .height(Constants.TEXT_DECORATION_HEIGHT) 424 } 425 } 426 } 427 .onClick(() => { 428 }) 429 } 430 .padding({ 431 left: Constants.DEFAULT_PADDING_START, 432 right: Constants.DEFAULT_PADDING_END 433 }) 434 .margin({ top: Constants.TERTIARY_LISTITEM_MARGIN_TOP }) 435 }, item => item.toString()) 436 } 437 .borderRadius(Constants.BORDER_RADIUS) 438 .backgroundColor($r('app.color.default_background_color')) 439 .padding({ 440 top: Constants.TERTIARY_LIST_PADDING_TOP, bottom: Constants.TERTIARY_LIST_PADDING_BOTTOM 441 }) 442 443 if ((this.api >= Constants.API_VERSION_SUPPORT_STAGE) && (permissions.includes(PRECISE_LOCATION_PERMISSION))) { 444 Column() { 445 Row() { 446 Text($r('app.string.precise_location')) 447 .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE) 448 .fontColor($r('app.color.label_color')) 449 .fontWeight(FontWeight.Medium) 450 .flexGrow(Constants.FLEX_GROW) 451 Toggle({ type: ToggleType.Switch, isOn: this.accurateIsOn }) 452 .selectedColor($r('app.color.button_color')) 453 .switchPointColor($r('app.color.selected_Color')) 454 .onChange((isOn: boolean) => { 455 var acManager = abilityAccessCtrl.createAtManager() 456 if (isOn) { 457 acManager.grantUserGrantedPermission(bundleInfo.appInfo.accessTokenId, PRECISE_LOCATION_PERMISSION, Constants.PERMISSION_FLAG) 458 .then(() => { this.accurateIsOn = true }) 459 } else { 460 acManager.revokeUserGrantedPermission(bundleInfo.appInfo.accessTokenId, PRECISE_LOCATION_PERMISSION, Constants.PERMISSION_FLAG) 461 .then(() => { this.accurateIsOn = false }) 462 } 463 }) 464 .padding({ right: 0 }) 465 .enabled(this.isCheckList[0]) 466 }.width(Constants.FULL_WIDTH) 467 .height(Constants.LISTITEM_ROW_HEIGHT) 468 }.margin({ top: Constants.LOCATION_MARGIN_TOP, bottom: Constants.LOCATION_MARGIN_BOTTOM }) 469 .padding({ 470 left: Constants.DEFAULT_PADDING_START, 471 right: Constants.DEFAULT_PADDING_END, 472 top: Constants.TERTIARY_LIST_PADDING_TOP, 473 bottom: Constants.TERTIARY_LIST_PADDING_BOTTOM 474 }) 475 .borderRadius(Constants.BORDER_RADIUS) 476 .backgroundColor($r('app.color.default_background_color')) 477 478 Row() { 479 Text($r('app.string.get_the_exact_position')) 480 .fontSize(Constants.TEXT_SMAL_FONT_SIZE) 481 .fontColor($r('app.color.label_color_light')) 482 .lineHeight(Constants.TEXT_SMALL_LINE_HEIGHT) 483 }.width(Constants.FULL_WIDTH) 484 .padding({ 485 left: Constants.DEFAULT_PADDING_START, 486 right: Constants.DEFAULT_PADDING_END, 487 }) 488 } 489 } 490 .padding({ 491 left: Constants.LIST_PADDING_LEFT, 492 right: Constants.LIST_PADDING_LEFT 493 }) 494 .width(Constants.FULL_WIDTH) 495 .height(Constants.FULL_HEIGHT) 496 } 497 .width(Constants.FULL_WIDTH) 498 } 499} 500