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 ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility';
16import Want from '@ohos.app.ability.Want';
17import fileio from '@ohos.fileio';
18import dlpPermission from '@ohos.dlpPermission';
19import common from '@ohos.app.ability.common';
20import GlobalContext from '../common/GlobalContext';
21import { HiLog } from '../common/HiLog';
22import {
23  deleteSandbox2linkFileData,
24  deleteFileOpenHistoryData,
25  deleteLinkSetData,
26  deleteToken2FileData,
27} from '../common/DataUtils'
28
29const TAG = 'DataAbility';
30const INDEX_TWO = 2;
31const INDEX_ONE = 1;
32const INDEX_ZERO = 0;
33const INDEX_THREE = 3;
34
35export default class DataAbility extends ServiceExtensionAbility {
36  private isSubscriber = false;
37
38  async sandbox2linkFile(key: string) {
39    let sandbox2linkFile: Map<string, (number | string | dlpPermission.DLPFile)[][]> =
40      GlobalContext.load('sandbox2linkFile') as Map<string, (number | string | dlpPermission.DLPFile)[][]>;
41    if (sandbox2linkFile.has(key)) {
42      try {
43        await deleteSandbox2linkFileData(key, true);
44      } catch (err) {
45        HiLog.error(TAG, `deleteSandbox2linkFileData error`);
46      }
47      let fileOpenHistory:Map<string, (number | string)[]> =
48        GlobalContext.load('fileOpenHistory') as Map<string, (number | string)[]>;
49      for (let item of Array.from<(string | (number | string)[])[]>(fileOpenHistory)) {
50        if (item.length < INDEX_TWO || Object.keys(item[INDEX_ONE]).length < INDEX_TWO) {
51          continue;
52        }
53        let itemKey = item[INDEX_ZERO];
54        let itemValue = item[INDEX_ONE];
55        let tmp: string = (itemValue[INDEX_ZERO] as string) + (itemValue[INDEX_ONE] as number);
56        if (tmp === key && itemValue.length > INDEX_THREE) {
57          await deleteLinkSetData(itemValue[INDEX_THREE] as string);
58          await deleteFileOpenHistoryData(itemKey as string);
59        }
60      }
61    }
62    if (sandbox2linkFile.size === 0) {
63        HiLog.info(TAG, `sandbox2linkFile empty`);
64        (GlobalContext.load('dataContext') as common.ServiceExtensionContext).terminateSelf();
65        (AppStorage.get('viewContext') as common.ServiceExtensionContext).terminateSelf();
66    }
67  }
68
69  createSubscriber(): void {
70    HiLog.info(TAG, `createSubscriber`);
71    try {
72      dlpPermission.on('uninstallDLPSandbox', (data: dlpPermission.DLPSandboxState) => {
73        let bundleName: string = data.bundleName;
74        let sandboxAppIndex: number = data.appIndex;
75        let key: string = bundleName + sandboxAppIndex;
76
77        let token2File:Map<number, (number | string | dlpPermission.DLPFile)[]> =
78          GlobalContext.load('token2File') as Map<number, (number | string | dlpPermission.DLPFile)[]>;
79        for (let item of Array.from<(number | (number | string | dlpPermission.DLPFile)[])[]>(token2File)) {
80          if (item.length < INDEX_TWO || Object.keys(item[INDEX_ONE]).length < INDEX_THREE) {
81            continue;
82          }
83          let itemKey = item[INDEX_ZERO];
84          let itemValue = item[INDEX_ONE] as Record<number, Object>;
85          const APP_ID: string = (itemValue[INDEX_ONE] as string) + (itemValue[INDEX_TWO] as number);
86          if (key === APP_ID) {
87            deleteToken2FileData(itemKey as number);
88          }
89        }
90        try {
91          this.sandbox2linkFile(key);
92        } catch (err) {
93          HiLog.error(TAG, `release resource error: ${JSON.stringify(err)}`);
94        }
95      });
96      this.isSubscriber = true;
97    } catch (err) {
98      HiLog.info(TAG, `createSubscriber uninstallDLPSandbox failed: ${JSON.stringify(err)}`);
99    }
100  }
101
102  onCreate(want: Want): void {
103    const context = this.context;
104    GlobalContext.store('dataContext', context);
105  }
106
107  onRequest(want: Want, startId: number): void {
108    if (!this.isSubscriber) {
109      this.createSubscriber();
110    }
111  }
112
113  onDestroy(): void {
114    HiLog.info(TAG, `onDestroy`);
115    if (this.isSubscriber) {
116      HiLog.info(TAG, `cancelSubscriber uninstallDLPSandbox`);
117      try {
118        dlpPermission.off('uninstallDLPSandbox');
119        this.isSubscriber = false;
120      } catch (err) {
121        HiLog.error(TAG, `cancelSubscriber uninstallDLPSandbox error: ${JSON.stringify(err)}`);
122      }
123    }
124  }
125}
126