• 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 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