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 abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'; 17import i18n from '@ohos.i18n'; 18import hilog from '@ohos.hilog'; 19import { permissionGroups, groups } from '../model/permissionGroup'; 20import Constants from '../utils/constant'; 21import { BundleInfoUtils } from './bundleInfoUtils'; 22import { CommonUtils } from './commonUtils'; 23import { GroupInfo, AppInfo, ApplicationObj, PermissionInfo } from './typedef'; 24import systemParameterEnhance from '@ohos.systemParameterEnhance'; 25import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; 26import uiExtensionHost from '@ohos.uiExtensionHost'; 27import window from '@ohos.window'; 28import { GlobalContext } from './globalContext'; 29 30const TAG = 'PermissionManager_Log ' 31 32/** 33 * verify permission 34 * @param {Number} accessTokenId 35 * @param {String} permission permission name 36 */ 37export function verifyAccessToken(accessTokenId: number, permission: Permissions) { 38 return new Promise<number>((resolve) => { 39 let atManager = abilityAccessCtrl.createAtManager(); 40 let data = atManager.verifyAccessTokenSync(accessTokenId, permission); 41 if (data == abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) { 42 resolve(data); 43 } else { 44 try { 45 atManager.getPermissionFlags(accessTokenId, permission).then((flag: number) => { 46 if (flag == Constants.PERMISSION_COMPONENT_SET) { 47 resolve(abilityAccessCtrl.GrantStatus.PERMISSION_DENIED); 48 } else { 49 resolve(data); 50 } 51 }) 52 } catch (err) { 53 Log.error('getPermissionFlags error: ' + JSON.stringify(err)); 54 resolve(data); 55 } 56 } 57 }) 58} 59 60/** 61 * Omit display when application name is too long 62 * @param {String} Application name 63 */ 64export function titleTrim(title: string): string { 65 const length: number = title.length; 66 if (length > Constants.MAXIMUM_HEADER_LENGTH) { 67 let str = ''; 68 str = title.substring(0, Constants.MAXIMUM_HEADER_LENGTH) + '...'; 69 return str; 70 } else { 71 return title; 72 } 73} 74 75export const indexValue: string[] = [ 76 '#', 77 'A', 78 'B', 79 'C', 80 'D', 81 'E', 82 'F', 83 'G', 84 'H', 85 'I', 86 'J', 87 'K', 88 'L', 89 'M', 90 'N', 91 'O', 92 'P', 93 'Q', 94 'R', 95 'S', 96 'T', 97 'U', 98 'V', 99 'W', 100 'X', 101 'Y', 102 'Z' 103]; // Array of alphabetically indexed names 104 105export function addLocalTag(info: AppInfo) { 106 let isZh = i18n.System.getSystemLanguage().indexOf('zh') >= 0; 107 let appName: string = info.label; 108 let upperCase = CommonUtils.isEmpty(appName) ? '' : appName[0].toLocaleUpperCase(); 109 let regexEn: RegExp = new RegExp('[A-Z]'); 110 let regexNm: RegExp = new RegExp('[0-9]'); 111 112 if (isZh) { 113 if (upperCase.match(regexEn)) { 114 info.zhTag = BundleInfoUtils.getStringZh(appName); 115 info.indexTag = upperCase; 116 info.language = 'EN'; 117 } else { 118 info.zhTag = appName; 119 info.language = 'CN'; 120 if (upperCase.match(regexNm)) { 121 info.indexTag = '#'; 122 } else { 123 info.indexTag = BundleInfoUtils.findZhIndex(upperCase); 124 } 125 } 126 } else { 127 if (upperCase.match(regexEn)) { 128 info.zhTag = appName; 129 info.indexTag = upperCase; 130 info.language = 'EN'; 131 } else { 132 info.zhTag = appName; 133 info.indexTag = '#'; 134 info.language = 'CN'; 135 } 136 } 137} 138 139let enComparator = new Intl.Collator('en'); 140let zhComparator = new Intl.Collator('zh-Hans-CN'); 141 142export function sortByName(appArray: Array<AppInfo | ApplicationObj>): Array<AppInfo | ApplicationObj> { 143 return appArray.sort((item1: AppInfo | ApplicationObj, item2: AppInfo | ApplicationObj) => { 144 if (item1.indexTag !== item2.indexTag) { 145 return enComparator.compare(item1.indexTag, item2.indexTag); 146 } 147 148 let isEn1 = item1.language === 'EN'; 149 let isEn2 = item2.language === 'EN'; 150 151 if (isEn1 && isEn2) { 152 return enComparator.compare(item1.label, item2.label); 153 } else if (isEn1 && !isEn2) { 154 return 1; 155 } else if (!isEn1 && isEn2) { 156 return -1; 157 } else { 158 return zhComparator.compare(item1.zhTag, item2.zhTag); 159 } 160 }) 161} 162 163/** 164 * Get permission label 165 * @param {String} permission name 166 */ 167export function getPermissionLabel(permission: string): ResourceStr { 168 for (let i = 0; i < permissionGroups.length; i++) { 169 if (permissionGroups[i].permissionName == permission) { 170 return permissionGroups[i].label 171 } 172 } 173 return ''; 174} 175 176/** 177 * Get the corresponding permission group id according to the permission 178 * @param {String} permission app name id 179 * @return {GroupInfo} group 180 */ 181export function getPermissionGroup(permission: string): GroupInfo { 182 for (let i = 0; i < permissionGroups.length; i++) { 183 if (permissionGroups[i].permissionName == permission) { 184 return groups[permissionGroups[i].groupId]; 185 } 186 } 187 return groups[0]; 188} 189 190/** 191 * Obtain a permission group by its name 192 * @param {String} group name 193 * @return {GroupInfo} group 194 */ 195export function getPermissionGroupByName(name: string): GroupInfo { 196 for (let i = 0; i < groups.length; i++) { 197 if (groups[i].name === name) { 198 return groups[i]; 199 } 200 } 201 return groups[0]; 202} 203 204/** 205 * Obtain the permission group ID by permission name 206 * @param {String} permission name 207 * @return {number} groupId 208 */ 209export function getGroupIdByPermission(permission: string): number { 210 for (let i = 0; i < permissionGroups.length; i++) { 211 if (permissionGroups[i].permissionName === permission) { 212 return permissionGroups[i].groupId; 213 } 214 } 215 return 0; 216} 217 218export function PermissionDialogException(code: number, session: UIExtensionContentSession): void { 219 session.terminateSelfWithResult({ 220 resultCode: -1, 221 want: { 222 parameters: { 223 'ohos.user.setting.permission.result': [], 224 'ohos.user.setting.error_code': code, 225 } 226 } 227 }) 228} 229 230export function PermissionDialogReturn(resultArray: Array<number>, session: UIExtensionContentSession): void { 231 session.terminateSelfWithResult({ 232 resultCode: 0, 233 want: { 234 parameters: { 235 'ohos.user.setting.permission.result': resultArray, 236 'ohos.user.setting.error_code': 0 237 } 238 } 239 }) 240} 241 242// check if the permissions provided are in the same group 243export function checkPermissionGroup(appPermissions: Permissions[]): string | null { 244 if (appPermissions.length == 0) { 245 return null; 246 } 247 let groupName = '' // index of group in permissionGroup 248 // check if permission is a valid permission 249 for (const permission of appPermissions) { 250 let idx = permissionGroups.findIndex( 251 (item) => {return item.permissionName === permission} 252 ); 253 // if permission not found in known permissions , return false 254 if (idx == -1) { 255 Log.error(TAG + 'unknown info ' + permission) 256 return null; 257 } 258 // if groupName not set , set groupName 259 if (groupName == '') { 260 groupName = permissionGroups[idx].groupName; 261 } 262 // if current groupName is not the same to the previous , not the same group 263 if (permissionGroups[idx].groupName != groupName) { 264 Log.error(TAG + 'permission ' + permission + ' is not in current group ' + groupName) 265 return null 266 } 267 } 268 return groupName; 269} 270 271export function setAvoidArea(proxy: uiExtensionHost.UIExtensionHostWindowProxy) { 272 let avoidArea = proxy.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM); 273 let btmAvoidHeight: string = avoidArea.bottomRect.height.toString(); 274 Log.info(TAG + 'avoid area height: ' + btmAvoidHeight + 'px'); // assure unit in pixels 275 GlobalContext.store('avoidAreaHeight', btmAvoidHeight + 'px'); 276} 277 278export function getFontSizeScale(): number { 279 const FONT_SIZE_SCALE_PARAM = 'persist.sys.font_scale_for_user0'; 280 let fontSizeScale = Number.parseFloat(systemParameterEnhance.getSync(FONT_SIZE_SCALE_PARAM, '1')); 281 return fontSizeScale >= Constants.DIALOG_TITLE_MAX_SCALE ? Constants.DIALOG_TITLE_MAX_SCALE : fontSizeScale; 282} 283 284export function getLimitFontSize( 285 fontSizeScale: number, maxScale: number, resMin: Resource, resMax: Resource 286): number | string { 287 if (fontSizeScale <= 1) { 288 return px2vp(getContext().resourceManager.getNumber(resMin.id)); 289 } 290 let fontSize = px2vp(getContext().resourceManager.getNumber(resMax.id)); 291 return fontSizeScale > maxScale ? `${fontSize * maxScale}vp` : fontSize; 292} 293 294 295export class Log { 296 public static domain: number = 0x8214; 297 public static tag: string = 'PermissionManager_Log'; 298 299 public static debug(message: string): void { 300 hilog.debug(Log.domain, Log.tag, message); 301 } 302 303 public static info(message: string): void { 304 hilog.info(Log.domain, Log.tag, message); 305 } 306 307 public static warn(message: string): void { 308 hilog.warn(Log.domain, Log.tag, message); 309 } 310 311 public static error(message: string): void { 312 hilog.error(Log.domain, Log.tag, message); 313 } 314}