• 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 */
15import UIAbility from '@ohos.app.ability.UIAbility';
16import datafile from '@ohos.file.fileAccess';
17import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
18import { Permissions } from '@ohos.abilityAccessCtrl';
19import dlpPermission from '@ohos.dlpPermission';
20import emitter from '@ohos.events.emitter';
21import deviceInfo from '@ohos.deviceInfo';
22import Constants from '../common/constant';
23import { getAuthPerm, checkAccountLogin, getOsAccountInfo, judgeIsSandBox, getFileFd } from '../common/utils';
24import GlobalContext from '../common/GlobalContext'
25import { Configuration } from '@ohos.app.ability.Configuration';
26import Want from '@ohos.app.ability.Want';
27import AbilityConstant from '@ohos.app.ability.AbilityConstant';
28import { BusinessError } from '@ohos.base';
29import window from '@ohos.window';
30import osAccount from '@ohos.account.osAccount';
31import common from '@ohos.app.ability.common';
32
33const PHONE = 'phone';
34const TAG = '[DLPManager_Main]';
35let permissionList: Array<Permissions> = [
36  'ohos.permission.READ_MEDIA',
37  'ohos.permission.WRITE_MEDIA',
38  'ohos.permission.FILE_ACCESS_MANAGER'
39];
40
41let direction: number = -1;
42let languageValue: string = 'zh';
43
44export default class MainAbility extends UIAbility {
45  authPerm: dlpPermission.DLPFileAccess = dlpPermission.DLPFileAccess.READ_ONLY;
46  callerToken:number = 0;
47
48  async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
49    console.info(TAG, 'onCreate');
50    GlobalContext.store('abilityWant', want);
51    GlobalContext.store('context', this.context);
52    GlobalContext.store('domainAccount', deviceInfo.deviceType === PHONE ? false : true);
53    GlobalContext.store('uri', want.uri ?? '');
54
55    GlobalContext.store('dsHelper', datafile.createFileAccessHelper(this.context));
56    direction = this.context.config.direction ?? -1;
57    languageValue = this.context.config.language ?? 'zh';
58    if (!GlobalContext.load('fileOpenHistoryFromMain')) {
59      GlobalContext.store('fileOpenHistoryFromMain', new Map<string, (string | number)[]>());
60    }
61    if (!GlobalContext.load('linkSet')) {
62      GlobalContext.store('linkSet', new Set<string>());
63    }
64  }
65  onConfigurationUpdate(newConfig: Configuration): void {
66    if (direction !== newConfig.direction) {
67      direction = newConfig.direction ?? -1;
68    }
69    if (languageValue !== newConfig.language) {
70      languageValue = newConfig.language ?? 'zh';
71    }
72    let eventData: emitter.EventData = {
73      data: {
74        'direction': direction,
75      }};
76    let innerEvent: emitter.InnerEvent = {
77      eventId: Constants.ENCRYPTION_EMIT_DIRECTION_STATUS,
78      priority: emitter.EventPriority.HIGH
79    };
80    emitter.emit(innerEvent, eventData);
81
82    let languageData: emitter.EventData = {
83      data: {
84        'languageValue': languageValue,
85      }};
86    let languageEvent: emitter.InnerEvent = {
87      eventId: Constants.ENCRYPTION_EMIT_LANGUAGE_VALUE,
88      priority: emitter.EventPriority.HIGH
89    };
90    emitter.emit(languageEvent, languageData);
91  }
92
93  onDestroy(): void {
94    console.info(TAG, 'onDestroy');
95    if (GlobalContext.load('fileOpenHistoryFromMain')) {
96      (GlobalContext.load('fileOpenHistoryFromMain') as Map<string, Object>).delete(GlobalContext.load('uri') as string)
97    }
98  }
99
100  onNewWant(want: Want) {
101    console.log(TAG, 'onNewWant', JSON.stringify(want));
102    GlobalContext.store('abilityWant', want);
103    GlobalContext.store('uri', (GlobalContext.load('abilityWant') as Want).uri as string);
104
105    this.getNewWantPage();
106  }
107
108  async showErrorDialogAndExit(error: BusinessError): Promise<void> {
109    let abilityWant = GlobalContext.load('abilityWant') as Want;
110    if (abilityWant.parameters) {
111      abilityWant.parameters.error = error;
112    }
113    let context: common.UIAbilityContext = GlobalContext.load('context') as common.UIAbilityContext;
114    GlobalContext.store('alertContext', context);
115    (GlobalContext.load('windowStage') as window.WindowStage).loadContent('pages/alert', (err: BusinessError) => {
116      if (err.code !== 0) {
117        console.error(TAG, 'loadContent failed', err.code, err.message);
118      }
119    });
120  }
121
122  async gotoPage(windowStage: window.WindowStage, accountInfo: osAccount.OsAccountInfo): Promise<void> {
123    let accountName: string = (GlobalContext.load('domainAccount') as boolean) ? accountInfo.domainInfo.accountName : accountInfo.distributedInfo.name;
124    this.authPerm = getAuthPerm(accountName, (GlobalContext.load('dlpFile') as dlpPermission.DLPFile).dlpProperty);
125    console.info(TAG, accountName, 'has dlp access', JSON.stringify(this.authPerm));
126
127    AppStorage.SetOrCreate('authPerm', this.authPerm);
128    AppStorage.SetOrCreate<string>('contactAccount', (GlobalContext.load('dlpFile') as dlpPermission.DLPFile).dlpProperty.contactAccount);
129    if (this.authPerm < dlpPermission.DLPFileAccess.READ_ONLY ||
130      this.authPerm > dlpPermission.DLPFileAccess.FULL_CONTROL) {
131      await this.showErrorDialogAndExit({ code: Constants.ERR_JS_APP_INSIDE_ERROR } as BusinessError);
132      return;
133    }
134    if (this.authPerm === dlpPermission.DLPFileAccess.FULL_CONTROL) {
135      windowStage.loadContent('pages/changeEncryption', (err: BusinessError) =>{
136        if (err.code !== 0) {
137          console.error(TAG, 'loadContent failed', err.code, err.message);
138        }
139      });
140    } else {
141      windowStage.loadContent('pages/permissionStatus', (err: BusinessError) =>{
142        if (err.code !== 0) {
143          console.error(TAG, 'loadContent failed', err.code, err.message);
144        }
145      });
146    }
147    windowStage.getMainWindow().then((win: window.Window) => {
148      win.setBackgroundColor('#00FFFFFF');
149    });
150  }
151
152  async findDlpFile(): Promise<void> {
153    return new Promise(async (resolve, reject) => {
154      let abilityWant: Want = GlobalContext.load('abilityWant') as Want;
155      const linkFileName: string = (abilityWant.parameters?.linkFileName as Record<string, string>)?.name;
156      let sandbox2linkFile:Map<string, (number | string | dlpPermission.DLPFile)[][]> = GlobalContext.load('sandbox2linkFile') as Map<string, (number | string | dlpPermission.DLPFile)[][]>;
157      for (let value of Array.from<(number | string | dlpPermission.DLPFile)[][]>(sandbox2linkFile.values())) {
158        for (let linkFile of value) {
159          if (linkFile[Constants.FILE_OPEN_HISTORY_ONE] === linkFileName) {
160            if (this.callerToken !== linkFile[Constants.FILE_OPEN_HISTORY_THREE]) {
161              console.error(TAG, 'found file, buf token invalid', linkFileName);
162              await this.showErrorDialogAndExit({ code: Constants.ERR_JS_APP_INSIDE_ERROR } as BusinessError);
163              reject();
164              return;
165            }
166            GlobalContext.store('dlpFile', linkFile[Constants.FILE_OPEN_HISTORY_ZERO]);
167            GlobalContext.store('dlpFd', linkFile[Constants.FILE_OPEN_HISTORY_TWO]);
168            let dlpFileName: string = (abilityWant.parameters?.fileName as Record<string, string>)?.name;
169            GlobalContext.store('dlpFileName', dlpFileName);
170            GlobalContext.store('linkFileName', linkFileName);
171            console.info(TAG, 'find dlp file', dlpFileName, GlobalContext.load('dlpFd'));
172            resolve();
173            return;
174          }
175        }
176      }
177      console.error(TAG, 'request from sandbox, but can not find dlp file by linkFileName', linkFileName);
178      await this.showErrorDialogAndExit({ code: Constants.ERR_JS_APP_INSIDE_ERROR } as BusinessError);
179      reject();
180    });
181  }
182
183  async openDlpFile(): Promise<void> {
184    return new Promise(async (resolve, reject) => {
185      try {
186        let dlpFileName: string = ((GlobalContext.load('abilityWant')as Want).parameters?.fileName as Record<string, string>)?.name;
187        GlobalContext.store('dlpFileName', dlpFileName);
188        let dlpFd: number = getFileFd(GlobalContext.load('uri') as string);
189        GlobalContext.store('dlpFd', dlpFd);
190        console.info(TAG, 'openDLPFile', dlpFileName, dlpFd);
191        GlobalContext.store('dlpFile', await dlpPermission.openDLPFile(dlpFd));
192        resolve();
193      } catch (err) {
194        console.error(TAG, 'openDLPFile', GlobalContext.load('dlpFileName') as string, 'failed', (err as BusinessError).code, (err as BusinessError).message);
195        await this.showErrorDialogAndExit(err as BusinessError);
196        reject(err);
197      }
198    });
199  }
200
201  checkValidWant(): boolean {
202    let parameters = (GlobalContext.load('abilityWant') as Want).parameters;
203    if (parameters === undefined) {
204      console.error(TAG, 'need parameters in want');
205      return false;
206    }
207    if (parameters.fileName === undefined) {
208      console.error(TAG, 'need fileName in want.parameters');
209      return false;
210    }
211    if ((parameters.fileName as Record<string, string>).name === undefined) {
212      console.error(TAG, 'need name in want.parameters.fileName');
213      return false;
214    }
215    if ((GlobalContext.load('abilityWant') as Want).uri === undefined) {
216      console.error(TAG, 'need uri in want');
217      return false;
218    }
219    this.callerToken = parameters['ohos.aafwk.param.callerToken'] as number;
220    let callerBundleName: string = parameters['ohos.aafwk.param.callerBundleName'] as string;
221    if (this.callerToken === undefined || callerBundleName === undefined) {
222      console.error(TAG, 'need caller info in want.parameters');
223      return false;
224    }
225    let uri = String((GlobalContext.load('abilityWant') as Want).uri);
226    if ((GlobalContext.load('linkSet') as Set<string>).has(uri)) {
227      console.error(TAG, 'invalid uri for opened link uri');
228      return false;
229    }
230
231    if (uri.indexOf(Constants.FUSE_PATH) !== -1) {
232      console.error(TAG, 'invalid uri in want.uri');
233      return false;
234    }
235    return true;
236  }
237
238  async getNewWantPage(): Promise<void> {
239    console.log(TAG, 'getNewWantPage start');
240    let windowStage: window.WindowStage = GlobalContext.load('windowStage') as window.WindowStage;
241    if (!this.checkValidWant()) {
242      await this.showErrorDialogAndExit({ code: Constants.ERR_JS_APP_PARAM_ERROR } as BusinessError);
243      return;
244    }
245    let accountInfo: osAccount.OsAccountInfo;
246    try {
247      accountInfo = await getOsAccountInfo();
248    } catch (err) {
249      console.error(TAG, 'getOsAccountInfo failed', (err as BusinessError).code, (err as BusinessError).message);
250      await this.showErrorDialogAndExit({ code: Constants.ERR_JS_GET_ACCOUNT_ERROR } as BusinessError);
251      return;
252    }
253    if (!checkAccountLogin(accountInfo)) {
254      await this.showErrorDialogAndExit({ code: Constants.ERR_JS_APP_NO_ACCOUNT_ERROR } as BusinessError);
255      return;
256    }
257    let requestIsFromSandBox: boolean = await judgeIsSandBox();
258    GlobalContext.store('requestIsFromSandBox', requestIsFromSandBox);
259    console.info(TAG, 'request is from sandbox', requestIsFromSandBox);
260    if (requestIsFromSandBox) {
261      try {
262        await this.findDlpFile();
263      } catch {
264        return;
265      }
266    } else {
267      let fileName: string = ((GlobalContext.load('abilityWant') as Want).parameters?.fileName as Record<string, string>)?.name;
268      let isDlpSuffix: boolean = fileName.endsWith('.dlp');
269      if (!isDlpSuffix) {
270        console.info(TAG, fileName, 'is not a dlp file');
271        GlobalContext.store('originFileName', fileName);
272        GlobalContext.store('originFd', getFileFd(GlobalContext.load('uri') as string));
273        windowStage.loadContent('pages/encryptionProtection', (err: BusinessError) =>{
274          if (err.code !== 0) {
275            console.error(TAG, 'loadContent failed', err.code, err.message);
276          }
277        });
278        windowStage.getMainWindow().then((win: window.Window) => {
279          win.setBackgroundColor('#00FFFFFF');
280        });
281        return;
282      } else {
283        let uri: string = GlobalContext.load('uri') as string;
284        if ((GlobalContext.load('fileOpenHistory') as Map<string, (number | string)[]>)?.has(uri)) {
285          await this.showErrorDialogAndExit({ code: Constants.ERR_JS_APP_OPEN_REJECTED } as BusinessError);
286          return;
287        }
288        try {
289          await this.openDlpFile();
290        } catch {
291          return;
292        }
293        GlobalContext.store('fileOpenHistoryFromMain', new Map<string, (string | number)[]>());
294        let fileOpenHistoryFromMain: Map<string, (string | number)[]> = GlobalContext.load('fileOpenHistoryFromMain') as Map<string, (string | number)[]>;
295        fileOpenHistoryFromMain.set(uri, [uri, GlobalContext.load('dlpFileName') as string, GlobalContext.load('dlpFd') as number]);
296        console.log(TAG, 'fileOpenHistoryFromMain add', JSON.stringify(fileOpenHistoryFromMain));
297      }
298    }
299    this.gotoPage(windowStage, accountInfo);
300}
301
302  async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {
303    console.info(TAG, 'onWindowStageCreate');
304    GlobalContext.store('windowStage', windowStage);
305    try {
306      let atManager = abilityAccessCtrl.createAtManager();
307      await atManager.requestPermissionsFromUser(GlobalContext.load('context') as common.UIAbilityContext, permissionList);
308    } catch (err) {
309      console.error(TAG, 'requestPermissionsFromUser failed', err.code, err.message);
310      return;
311    }
312    this.getNewWantPage();
313  }
314
315  onWindowStageDestroy(): void {
316    console.info(TAG, 'onWindowStageDestroy');
317  }
318
319  onForeground(): void {
320    console.info(TAG, 'onForeground');
321  }
322
323  onBackground() {
324    console.info(TAG, 'onBackground');
325  }
326};
327