1/*
2 * Copyright (c) 2024 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 common from '@ohos.app.ability.common';
17import Want from '@ohos.app.ability.Want';
18import { BusinessError } from '@ohos.base';
19import rpc from '@ohos.rpc';
20import DomainAccountRequest from '../../bean/request/DomainAccountRequest';
21import DomainAccountResponse from '../../bean/response/DomainAccountResponse';
22import DomainAccountConvertor from '../../convertor/DomainAccountConvertor';
23import Constants from '../constant';
24import AppStorageConstant from '../constant/AppStorageConstant';
25import { HiLog } from '../HiLog';
26import CredCallbackStub from '../share/CredCallback';
27
28const TAG = 'CredConnection';
29
30export default class CredConnection {
31  private static readonly CRED_BUNDLE_NAME = 'com.huawei.hmos.dlpcredmgr';
32  private static readonly CRED_ABILITY_NAME = 'DlpCredDataExtAbility';
33  private static readonly CRED_CALLBACK_STUB = 'CredCallbackStub';
34  private static readonly CRED_INTERFACE_TOKEN = 'OHOS.HapDlpCredAbilityServiceStub';
35  private static readonly REQUEST_TIME_OUT: number = 10;
36  private static readonly CONNECT_TIME_OUT: number = 1000;
37
38  private context: ESObject;
39  private connectionNum = -1;
40  private commonOption: common.ConnectOptions;
41  private remoteProxy: rpc.IRemoteObject | null = null;
42
43  constructor(context: ESObject) {
44    this.context = context;
45    this.commonOption = {
46      onConnect: (elementName, remote) => {
47        this.remoteProxy = remote;
48        HiLog.info(TAG, `onConnect success`);
49      },
50      onDisconnect: () => {
51        HiLog.info(TAG, `onDisconnect`);
52      },
53      onFailed: () => {
54        HiLog.info(TAG, `onFailed`);
55      }
56    }
57  }
58
59  public getRemoteProxy(): rpc.IRemoteObject | null {
60    return this.remoteProxy;
61  }
62
63  connectDomainAccountQueryAbility() {
64    this.connectServiceAbility(Constants.COMMAND_GET_DOMAIN_ACCOUNT_INFO);
65  }
66
67  private connectServiceAbility(code: number) {
68    HiLog.info(TAG, `connectServiceAbility start`);
69    let want: Want = {
70      bundleName: CredConnection.CRED_BUNDLE_NAME,
71      abilityName: CredConnection.CRED_ABILITY_NAME,
72    };
73    try {
74      switch (code) {
75        case Constants.COMMAND_GET_DOMAIN_ACCOUNT_INFO: {
76          this.connectionNum = this.context.connectServiceExtensionAbility(want, this.commonOption);
77          break;
78        }
79        default: {
80          HiLog.error(TAG, `code is not exist ${code}`);
81        }
82      }
83    } catch (err) {
84      HiLog.error(TAG, `connectServiceAbility failed: ${JSON.stringify(err)}`);
85    }
86    AppStorage.setOrCreate(AppStorageConstant.CRED_CONNECTION_NUM, this.connectionNum);
87    HiLog.info(TAG, `connectServiceAbility result: ${this.connectionNum}`);
88  }
89
90  private waitConnect() {
91    if (this.remoteProxy) {
92      return;
93    }
94    let currentTime = new Date().getTime();
95    while (!this.remoteProxy && new Date().getTime() < currentTime + CredConnection.CONNECT_TIME_OUT) {
96      continue;
97    }
98  }
99
100  async getDomainAccountInfo(req: DomainAccountRequest): Promise<DomainAccountResponse | undefined> {
101    HiLog.info(TAG, `getDomainAccountInfo start`);
102    let result: DomainAccountResponse | undefined;
103    let option = new rpc.MessageOption(Constants.TF_SYNC, CredConnection.REQUEST_TIME_OUT);
104    let data = new rpc.MessageSequence();
105    let reply = new rpc.MessageSequence();
106    try {
107      data.writeInterfaceToken(CredConnection.CRED_INTERFACE_TOKEN);
108      let callback: CredCallbackStub = new CredCallbackStub(CredConnection.CRED_CALLBACK_STUB);
109      data.writeRemoteObject(callback.asObject());
110      data.writeString(JSON.stringify(req));
111      this.waitConnect();
112      if (!this.remoteProxy) {
113        HiLog.error(TAG, `onConnect remote is null.`);
114        return result;
115      }
116      let sendResult = await this.remoteProxy.sendMessageRequest(
117        Constants.COMMAND_GET_DOMAIN_ACCOUNT_INFO, data, reply, option);
118      let code = sendResult.reply.readInt();
119      if (code !== Constants.INTERFACE_SUCCESS) {
120        HiLog.info(TAG, `getDomainAccountInfo sendMessageRequest is error, code: ${code}`);
121        return result;
122      }
123      result = DomainAccountConvertor.convertToDomainAccountResp(sendResult.reply.readString());
124    } catch (error) {
125      HiLog.error(TAG, `getDomainAccountInfo result: ${error}`);
126    } finally {
127      data.reclaim();
128      reply.reclaim();
129    }
130    HiLog.info(TAG, `getDomainAccountInfo end`);
131    return result;
132  }
133
134
135  disconnectServiceAbility() {
136    HiLog.info(TAG, `disconnectServiceAbility: ${AppStorage.get(AppStorageConstant.CRED_CONNECTION_NUM)}`);
137    let connectionNum: number | undefined = AppStorage.get(AppStorageConstant.CRED_CONNECTION_NUM);
138    if (!connectionNum || connectionNum < 0) {
139      return;
140    }
141    this.context.disConnectServiceExtensionAbility(connectionNum).then(() => {
142      HiLog.info(TAG, `disconnectServiceAbility success.`);
143    }).catch((error: BusinessError) => {
144      HiLog.error(TAG, `disconnectServiceAbility failed. Error: ${JSON.stringify(error)}`);
145    })
146  };
147}