1/* 2 * Copyright (c) 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 UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; 17import UIExtensionAbility from '@ohos.app.ability.UIExtensionAbility'; 18import dlpPermission from '@ohos.dlpPermission'; 19import emitter from '@ohos.events.emitter'; 20import Want from '@ohos.app.ability.Want'; 21import { BusinessError } from '@ohos.base'; 22import osAccount from '@ohos.account.osAccount'; 23import { Configuration } from '@ohos.app.ability.Configuration'; 24import Constants from '../common/constant'; 25import { 26 getAuthPerm, 27 checkDomainAccountInfo, 28 getOsAccountInfo, 29 judgeIsSandBox, 30 getFileFd, 31 getAppId, 32 isPC, 33 DLPInfo, 34 getDLPInfo, 35 sendDlpManagerAccountLogin, 36 isValidPath, 37 startAlertAbility 38} from '../common/utils'; 39import GlobalContext from '../common/GlobalContext'; 40import HomeFeature from '../feature/HomeFeature'; 41import { AccountTipsConfig } from '../common/AccountTipsConfig'; 42import common from '@ohos.app.ability.common'; 43 44const TAG = '[DLPManager_MainEx]'; 45 46let direction: number = -1; 47let colorMode: number = -1; 48 49export default class MainAbility extends UIExtensionAbility { 50 authPerm: dlpPermission.DLPFileAccess = dlpPermission.DLPFileAccess.READ_ONLY; 51 callerToken:number = 0; 52 private homeFeature!: HomeFeature; 53 54 async onSessionCreate(want: Want, session: UIExtensionContentSession): Promise<void> { 55 console.log(TAG, 'want', JSON.stringify(want)); 56 if (GlobalContext.load('session')) { 57 await startAlertAbility(this.context as common.UIExtensionContext, 58 { code: Constants.ERR_JS_APP_ENCRYPTING, 59 data: GlobalContext.load('abilityWant').parameters?.displayName 60 } as BusinessError, session); 61 return; 62 } 63 GlobalContext.store('session', session); 64 let dlpInfo:DLPInfo = await getDLPInfo(); 65 GlobalContext.store('hiPNameId', dlpInfo.name); 66 GlobalContext.store('hiPVersionId', dlpInfo.versionCode); 67 GlobalContext.store('abilityWant', want); 68 GlobalContext.store('context', this.context); 69 GlobalContext.store('domainAccount', !isPC() ? false : true); 70 GlobalContext.store('uri', want.uri ?? ''); 71 direction = this.context.config.direction ?? -1; 72 73 this.homeFeature = new HomeFeature(this.context); 74 GlobalContext.store('homeFeature', this.homeFeature); 75 76 this.homeFeature.connectServiceExtAbility(()=>{ 77 this.getNewWantPage(session); 78 }); 79 } 80 81 onConfigurationUpdate(newConfig: Configuration): void { 82 if (direction !== newConfig.direction) { 83 direction = newConfig.direction ?? -1; 84 } 85 let eventData: emitter.EventData = { 86 data: { 87 'direction': direction, 88 }}; 89 let innerEvent: emitter.InnerEvent = { 90 eventId: Constants.ENCRYPTION_EMIT_DIRECTION_STATUS, 91 priority: emitter.EventPriority.HIGH 92 }; 93 emitter.emit(innerEvent, eventData); 94 95 if (colorMode !== newConfig.colorMode) { 96 colorMode = newConfig.colorMode ?? -1; 97 } 98 let colorData: emitter.EventData = { 99 data: { 100 'colorMode': colorMode, 101 }}; 102 let colorEvent: emitter.InnerEvent = { 103 eventId: Constants.ENCRYPTION_EMIT_COLOR_MODE, 104 priority: emitter.EventPriority.HIGH 105 }; 106 emitter.emit(colorEvent, colorData); 107 } 108 109 onSessionDestroy(session: UIExtensionContentSession): void { 110 console.info(TAG, 'onSessionDestroy'); 111 if (session === GlobalContext.load('session')) { 112 GlobalContext.store('session', ''); 113 } 114 if (!(GlobalContext.load('requestIsFromSandBox') as boolean)) { 115 this.homeFeature.closeDLPFileHome(GlobalContext.load('uri'), (err: number) => { 116 if (err !== 0) { 117 console.error(TAG, 'closeDLPFile failed', err); 118 } 119 }); 120 } 121 } 122 123 async gotoPage(session: UIExtensionContentSession): Promise<void> { 124 let accountInfo: osAccount.OsAccountInfo = GlobalContext.load('accountInfo'); 125 let accountName: string = (GlobalContext.load('domainAccount') as boolean) ? accountInfo.domainInfo.accountName : accountInfo.distributedInfo.name; 126 this.authPerm = getAuthPerm(accountName, GlobalContext.load('dlpProperty')); 127 128 AppStorage.setOrCreate('authPerm', this.authPerm); 129 AppStorage.setOrCreate<string>('contactAccount', GlobalContext.load('dlpProperty').contactAccount); 130 AppStorage.setOrCreate('validity', GlobalContext.load('dlpProperty').expireTime) 131 if (this.authPerm < dlpPermission.DLPFileAccess.READ_ONLY || 132 this.authPerm > dlpPermission.DLPFileAccess.FULL_CONTROL) { 133 await startAlertAbility(GlobalContext.load('context') as common.UIExtensionContext, 134 { code: Constants.ERR_JS_APP_INSIDE_ERROR } as BusinessError, session); 135 return; 136 } 137 if (this.authPerm === dlpPermission.DLPFileAccess.FULL_CONTROL) { 138 if (GlobalContext.load('domainAccount') as boolean) { 139 try { 140 await this.checkValidEnterpriseAndAccount(session); 141 } catch { 142 return; 143 } 144 } 145 146 let storage: LocalStorage = new LocalStorage({ 147 'session': session, 148 } as Record<string, UIExtensionContentSession | string>); 149 session.loadContent('pages/changeEncryption', storage); 150 try { 151 session.setWindowBackgroundColor(Constants.TRANSPARENT_GREY_BACKGROUND_COLOR); 152 } catch (exception) { 153 console.error('Failed to set the background color. Cause: ' + JSON.stringify(exception)); 154 } 155 } else { 156 let storage: LocalStorage = new LocalStorage({ 157 'session': session, 158 } as Record<string, UIExtensionContentSession | string>); 159 session.loadContent('pages/permissionStatus', storage); 160 try { 161 session.setWindowBackgroundColor(Constants.TRANSPARENT_BACKGROUND_COLOR); 162 } catch (exception) { 163 console.error('Failed to set the background color. Cause: ' + JSON.stringify(exception)); 164 } 165 } 166 } 167 168 async checkValidWant(): Promise<boolean> { 169 let parameters = (GlobalContext.load('abilityWant') as Want).parameters; 170 if (parameters === undefined) { 171 console.error(TAG, 'need parameters in want'); 172 return false; 173 } 174 if (parameters.fileName === undefined) { 175 console.error(TAG, 'need fileName in want.parameters'); 176 return false; 177 } 178 if ((parameters.fileName as Record<string, string>).name === undefined) { 179 console.error(TAG, 'need name in want.parameters.fileName'); 180 return false; 181 } 182 if ((GlobalContext.load('abilityWant') as Want).uri === undefined) { 183 console.error(TAG, 'need uri in want'); 184 return false; 185 } 186 this.callerToken = parameters['ohos.aafwk.param.callerToken'] as number; 187 let callerBundleName: string = parameters['ohos.aafwk.param.callerBundleName'] as string; 188 if (this.callerToken === undefined || callerBundleName === undefined) { 189 console.error(TAG, 'need caller info in want.parameters'); 190 return false; 191 } 192 GlobalContext.store('hiPkgName', callerBundleName); 193 let uri = String((GlobalContext.load('abilityWant') as Want).uri); 194 if (!isValidPath(uri)) { 195 console.error(TAG, 'invalid uri in want.uri'); 196 return false; 197 } 198 try { 199 await new Promise<void>((resolve, reject) => { 200 this.homeFeature.linkSetHome(uri, (err: number) => { 201 if (err === 0) { 202 console.error(TAG, 'invalid uri for opened link uri'); 203 reject(); 204 } 205 resolve(); 206 }) 207 }) 208 } catch { 209 return false; 210 } 211 212 if (uri.indexOf(Constants.FUSE_PATH) !== -1) { 213 console.error(TAG, 'invalid uri in want.uri'); 214 return false; 215 } 216 return true; 217 } 218 219 async checkValidEnterpriseAndAccount(session: UIExtensionContentSession): Promise<void> { 220 return new Promise(async (resolve, reject) => { 221 let accountInfo: osAccount.OsAccountInfo = GlobalContext.load('accountInfo'); 222 AccountTipsConfig.getAccountInfo(accountInfo.domainInfo.accountName) 223 .then(() => { 224 resolve(); 225 }) 226 .catch(async (error: BusinessError) => { 227 await startAlertAbility(GlobalContext.load('context') as common.UIExtensionContext, 228 error, session); 229 reject(); 230 return; 231 }) 232 }) 233 } 234 235 async checkValidWantAndAccount(session: UIExtensionContentSession): Promise<void> { 236 return new Promise(async (resolve, reject) => { 237 if (!this.checkValidWant()) { 238 await startAlertAbility(GlobalContext.load('context') as common.UIExtensionContext, 239 { code: Constants.ERR_JS_APP_PARAM_ERROR } as BusinessError, session); 240 reject(); 241 return; 242 } 243 let accountInfo: osAccount.OsAccountInfo; 244 try { 245 accountInfo = await getOsAccountInfo(); 246 GlobalContext.store('accountInfo', accountInfo); 247 resolve(); 248 } catch (err) { 249 console.error(TAG, 'getOsAccountInfo failed', (err as BusinessError).code, (err as BusinessError).message); 250 await startAlertAbility(GlobalContext.load('context') as common.UIExtensionContext, 251 { code: Constants.ERR_JS_GET_ACCOUNT_ERROR } as BusinessError, session); 252 reject(); 253 return; 254 } 255 }) 256 } 257 258 async getNewWantPage(session: UIExtensionContentSession): Promise<void> { 259 console.log(TAG, 'getNewWantPage start'); 260 try { 261 await this.checkValidWantAndAccount(session) 262 } catch { 263 return; 264 } 265 let codeMessage = checkDomainAccountInfo(GlobalContext.load('accountInfo')); 266 sendDlpManagerAccountLogin(0); 267 if (codeMessage) { 268 await startAlertAbility(GlobalContext.load('context') as common.UIExtensionContext, 269 { code: codeMessage } as BusinessError, session); 270 return; 271 } 272 let requestIsFromSandBox: boolean = await judgeIsSandBox(); 273 GlobalContext.store('requestIsFromSandBox', requestIsFromSandBox); 274 console.info(TAG, 'request is from sandbox', requestIsFromSandBox); 275 if (requestIsFromSandBox) { 276 let abilityWant: Want = GlobalContext.load('abilityWant') as Want; 277 const linkFileName: string = (abilityWant.parameters?.linkFileName as Record<string, string>)?.name; 278 this.homeFeature.sandBoxLinkFileHome(linkFileName, this.callerToken, (err: number, data: dlpPermission.DLPProperty, uri: string) => { 279 if (err !== 0) { 280 return; 281 } 282 let dlpFileName: string = (abilityWant.parameters?.fileName as Record<string, string>)?.name; 283 GlobalContext.store('dlpFileName', dlpFileName); 284 GlobalContext.store('linkFileName', linkFileName); 285 GlobalContext.store('dlpProperty', data); 286 GlobalContext.store('uri', uri ?? ''); 287 GlobalContext.store('permanent', data.expireTime === 0); 288 if (data.expireTime !== 0) { 289 GlobalContext.store('validity', new Date(data.expireTime as number)); 290 } 291 this.gotoPage(session); 292 }); 293 } else { 294 let fileName: string = ((GlobalContext.load('abilityWant') as Want).parameters?.fileName as Record<string, string>)?.name; 295 let isDlpSuffix: boolean = fileName.endsWith('.dlp'); 296 if (!isDlpSuffix) { 297 console.info(TAG, fileName, 'is not a dlp file'); 298 GlobalContext.store('originFileName', fileName); 299 GlobalContext.store('originFd', getFileFd(GlobalContext.load('uri') as string)); 300 let storage: LocalStorage = new LocalStorage({ 301 'session': session, 302 } as Record<string, UIExtensionContentSession | string>); 303 session.loadContent('pages/encryptionProtection', storage); 304 try { 305 session.setWindowBackgroundColor(Constants.TRANSPARENT_GREY_BACKGROUND_COLOR); 306 } catch (exception) { 307 console.error('Failed to set the background color. Cause: ' + JSON.stringify(exception)); 308 } 309 return; 310 } else { 311 let uri: string = GlobalContext.load('uri') as string; 312 try { 313 await new Promise<void>((resolve, reject) => { 314 this.homeFeature.fileOpenHistoryHome(uri, async (err: number) => { 315 if (err === 0) { 316 await startAlertAbility(GlobalContext.load('context') as common.UIExtensionContext, 317 { code: Constants.ERR_JS_APP_OPEN_REJECTED } as BusinessError, session); 318 reject(); 319 } 320 resolve(); 321 }) 322 }) 323 } catch { 324 return; 325 } 326 let dlpFileName: string = ((GlobalContext.load('abilityWant')as Want).parameters?.fileName as Record<string, string>)?.name; 327 GlobalContext.store('dlpFileName', dlpFileName); 328 let callerAppId: string; 329 try { 330 let callerBundleName = Constants.DLP_MANAGER_BUNDLE_NAME; 331 callerAppId = await getAppId(callerBundleName); 332 console.info(TAG, 'get AppId', callerAppId); 333 } catch { 334 console.log(TAG, 'get AppId failed'); 335 return; 336 } 337 this.homeFeature.openDlpFileHome(uri, callerAppId, async (err: number, data: dlpPermission.DLPProperty, msg: string) => { 338 if (err !== 0) { 339 let ansErr: BusinessError<void> = { 340 code: err, 341 name: '', 342 message: msg, 343 } 344 await startAlertAbility(GlobalContext.load('context') as common.UIExtensionContext, 345 ansErr as BusinessError, session); 346 return; 347 } else { 348 GlobalContext.store('dlpProperty', data); 349 GlobalContext.store('permanent', data.expireTime === 0); 350 if (data.expireTime !== 0) { 351 GlobalContext.store('validity', new Date(data.expireTime as number)); 352 } 353 this.gotoPage(session); 354 } 355 }) 356 } 357 } 358 } 359 360 onWindowStageDestroy(): void { 361 console.info(TAG, 'onWindowStageDestroy'); 362 } 363 364 onForeground(): void { 365 console.info(TAG, 'onForeground'); 366 } 367 368 onBackground() { 369 console.info(TAG, 'onBackground'); 370 } 371}; 372