1/* 2 * Copyright (c) 2025 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 { BasePermissionStrategy } from '../base/BasePermissionStrategy'; 17import { LocationStrategy } from './LocationStrategy'; 18import { CameraStrategy } from './CameraStrategy'; 19import { MicrophoneStrategy } from './MicrophoneStrategy'; 20import { ContactsStrategy } from './ContactsStrategy'; 21import { CalendarStrategy } from './CalendarStrategy'; 22import { SportStrategy } from './SportStrategy'; 23import { HealthStrategy } from './HealthStrategy'; 24import { ImageAndVideosStrategy } from './ImageAndVideosStrategy'; 25import { AudioStrategy } from './AudiosStrategy'; 26import { DocumentsStrategy } from './DocumentsStrategy'; 27import { AdsStrategy } from './AdsStrategy'; 28import { GetInstalledBundleListStrategy } from './GetInstalledBundleListStrategy'; 29import { DistributedDatasyncStrategy } from './DistributedDatasyncStrategy'; 30import { BluetoothStrategy } from './BluetoothStrategy'; 31import { PasteboardStrategy } from './PasteboardStrategy'; 32import { DownloadDirectoryStrategy } from './DownloadDirectoryStrategy'; 33import { DesktopDirectoryStrategy } from './DesktopDirectoryStrategy'; 34import { DocumentsDirectoryStrategy } from './DocumentsDirectoryStrategy'; 35import { NearlinkStrategy } from './NearlinkStrategy'; 36import { ScreenCaptureStrategy } from './ScreenCaptureStrategy'; 37import { Permission, PermissionGroup, PermissionOption, ButtonStatus, ClickOption } from '../model/definition'; 38import { PermissionGroupConfig, CallerAppInfo, PermissionWithOption } from '../model/typedef'; 39import { Log } from '../utils/utils'; 40import common from '@ohos.app.ability.common'; 41 42export class PermissionGroupManager { 43 private permissionStrategies: Map<PermissionGroup, BasePermissionStrategy> = new Map(); 44 private static instance: PermissionGroupManager; 45 46 private constructor() { 47 // 位置信息 48 this.permissionStrategies.set(PermissionGroup.LOCATION, new LocationStrategy()); 49 // 相机 50 this.permissionStrategies.set(PermissionGroup.CAMERA, new CameraStrategy()); 51 // 麦克风 52 this.permissionStrategies.set(PermissionGroup.MICROPHONE, new MicrophoneStrategy()); 53 // 通讯录 54 this.permissionStrategies.set(PermissionGroup.CONTACTS, new ContactsStrategy()); 55 // 日历 56 this.permissionStrategies.set(PermissionGroup.CALENDAR, new CalendarStrategy()); 57 // 运动健身 58 this.permissionStrategies.set(PermissionGroup.SPORT, new SportStrategy()); 59 // 身体传感器 60 this.permissionStrategies.set(PermissionGroup.HEALTH, new HealthStrategy()); 61 // 图片和视频 62 this.permissionStrategies.set(PermissionGroup.IMAGE_AND_VIDEOS, new ImageAndVideosStrategy()); 63 // 音频 64 this.permissionStrategies.set(PermissionGroup.AUDIOS, new AudioStrategy()); 65 // 文件 66 this.permissionStrategies.set(PermissionGroup.DOCUMENTS, new DocumentsStrategy()); 67 // 应用跟踪 68 this.permissionStrategies.set(PermissionGroup.ADS, new AdsStrategy()); 69 // 读取已安装应用列表 70 this.permissionStrategies.set(PermissionGroup.GET_INSTALLED_BUNDLE_LIST, new GetInstalledBundleListStrategy()); 71 // 附近设备 72 this.permissionStrategies.set(PermissionGroup.DISTRIBUTED_DATASYNC, new DistributedDatasyncStrategy()); 73 // 蓝牙 74 this.permissionStrategies.set(PermissionGroup.BLUETOOTH, new BluetoothStrategy()); 75 // 剪贴板 76 this.permissionStrategies.set(PermissionGroup.PASTEBOARD, new PasteboardStrategy()); 77 // 文件夹 78 this.permissionStrategies.set(PermissionGroup.DOWNLOAD_DIRECTORY, new DownloadDirectoryStrategy()); 79 this.permissionStrategies.set(PermissionGroup.DESKTOP_DIRECTORY, new DesktopDirectoryStrategy()); 80 this.permissionStrategies.set(PermissionGroup.DOCUMENTS_DIRECTORY, new DocumentsDirectoryStrategy()); 81 // 星闪 82 this.permissionStrategies.set(PermissionGroup.NEARLINK, new NearlinkStrategy()); 83 // 截屏 84 this.permissionStrategies.set(PermissionGroup.CUSTOM_SCREEN_CAPTURE, new ScreenCaptureStrategy()); 85 } 86 87 public static getInstance(): PermissionGroupManager { 88 if (!PermissionGroupManager.instance) { 89 PermissionGroupManager.instance = new PermissionGroupManager(); 90 } 91 return PermissionGroupManager.instance; 92 } 93 94 /** 95 * 获取所有权限组config 96 * return 97 */ 98 public getAllGroupConfigs(): PermissionGroupConfig[] { 99 let allConfig: PermissionGroupConfig[] = []; 100 this.permissionStrategies.forEach((strategy, permissionGroup) => { 101 allConfig.push(strategy.getPermissionGroupConfig()); 102 }) 103 return allConfig; 104 } 105 106 /** 107 * 根据权限获取所在权限组名 108 * @param permission 权限 109 * @param allConfigs 110 * return 111 */ 112 public getGroupNameByPermission( 113 permission: Permission, allConfigs: PermissionGroupConfig[] 114 ): PermissionGroup | undefined { 115 for (let index = 0; index < allConfigs.length; index++) { 116 const element = allConfigs[index]; 117 if (element.permissions.includes(permission)) { 118 return element.groupName; 119 } 120 } 121 Log.error(`can not find permissionGroup, permission: ${permission}`); 122 return undefined; 123 } 124 125 /** 126 * 预处理待授权权限 127 * @param permission 权限 128 * @param groupName 权限组名 129 * @param tokenId 应用token 130 * return 131 */ 132 public async preProcessPermission( 133 permission: Permission, groupName: PermissionGroup, tokenId: number 134 ): Promise<PermissionWithOption[]> { 135 const groupHandle = this.permissionStrategies.get(groupName); 136 if (groupHandle === undefined) { 137 return []; 138 } 139 let result = await groupHandle.preProcessingPermission(permission, tokenId); 140 return result; 141 } 142 143 /** 144 * 根据带申请权限获取所有权限组列表 145 * @param callerAppInfo 调用方信息 146 * @param context 应用上下文 147 * @param appName 应用名 148 * @param locationFlag 位置权限组flag 149 * @param pasteBoardName 剪贴板信息 150 * return 151 */ 152 public getGroupConfigs( 153 callerAppInfo: CallerAppInfo, 154 context: common.ServiceExtensionContext, 155 appName: string, 156 locationFlag: number, 157 pasteBoardName: string 158 ): PermissionGroupConfig[] { 159 let groupConfigList: PermissionGroupConfig[] = []; 160 callerAppInfo.groupWithPermission.forEach((permissions, permissionGroup) => { 161 let groupHandle = this.permissionStrategies.get(permissionGroup); 162 if (groupHandle === undefined || groupHandle === null) { 163 Log.error(`get groupHandle faild, group: ${permissionGroup}.`); 164 return; 165 } 166 let groupConfig: PermissionGroupConfig = groupHandle.getPermissionGroupConfig(); 167 let title: ResourceStr = groupHandle.getGroupTitle(appName, locationFlag); 168 let readAndWrite: ResourceStr = groupHandle.getReadAndWrite(permissions); 169 let reason: ResourceStr = 170 groupHandle.getReasonByPermission(groupConfig.permissions, permissions, context, callerAppInfo, pasteBoardName); 171 groupConfigList.push(new PermissionGroupConfig({ 172 groupName: groupConfig.groupName, 173 permissions: groupConfig.permissions, 174 icon: groupConfig.icon, 175 title, 176 readAndWrite, 177 reason, 178 buttonList: groupHandle.getButtonList() 179 })) 180 }) 181 return groupConfigList; 182 } 183 184 /** 185 * 根据点击状态,返回当前权限对应的操作 186 * @param permission 权限 187 * @param groupName 权限组名 188 * @param callerAppInfo 调用方信息 189 * @param locationFlag 位置权限组flag 190 * @param buttonStatus 191 * return 192 */ 193 public getPermissionOption( 194 permission: Permission, 195 groupName: PermissionGroup, 196 callerAppInfo: CallerAppInfo, 197 locationFlag: number, 198 buttonStatus: ButtonStatus 199 ): PermissionOption { 200 const groupHandle = this.permissionStrategies.get(groupName); 201 let situation: ClickOption = this.getClickSituation(buttonStatus); 202 if (groupHandle) { 203 if (situation === ClickOption.GRANT) { 204 return groupHandle.grantHandle(permission, callerAppInfo, locationFlag, buttonStatus); 205 } else if (situation === ClickOption.DENY) { 206 return groupHandle.denyHandle(permission, callerAppInfo, locationFlag, buttonStatus); 207 } else { 208 return PermissionOption.SKIP; 209 } 210 } 211 return PermissionOption.SKIP; 212 } 213 214 /** 215 * 处理点击状态 216 * @param buttonStatus 217 * return 218 */ 219 public getClickSituation(buttonStatus: ButtonStatus): ClickOption { 220 switch (buttonStatus) { 221 case ButtonStatus.ALLOW: 222 case ButtonStatus.ALLOW_THIS_TIME: 223 case ButtonStatus.THIS_TIME_ONLY: 224 case ButtonStatus.ALLOW_ONLY_DURING_USE: 225 return ClickOption.GRANT; 226 case ButtonStatus.CANCEL: 227 return ClickOption.CANCEL; 228 default: 229 return ClickOption.DENY; 230 } 231 } 232 233}