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