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