• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 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 */
15let rpc = requireNapi('rpc');
16let accessControl = requireNapi('abilityAccessCtrl');
17let hilog = requireNapi('hilog');
18
19let domainID = 0xD001320;
20let TAG = 'JSENV';
21
22const EVENT_CALL_NOTIFY = 1;
23const REQUEST_SUCCESS = 0;
24const REQUEST_FAILED = 1;
25const PERMISSION_ABILITY_BACKGROUND_COMMUNICATION = 'ohos.permission.ABILITY_BACKGROUND_COMMUNICATION';
26
27const ERROR_CODE_INVALID_PARAM = 401;
28const ERROR_CODE_FUNC_REGISTERED = 16200004;
29const ERROR_CODE_FUNC_NOT_EXIST = 16200005;
30const ERROR_CODE_INNER_ERROR = 16000050;
31
32const ERROR_MSG_INVALID_PARAM = 'Invalid input parameter.';
33const ERROR_MSG_FUNC_REGISTERED = 'Method registered. The method has registered.';
34const ERROR_MSG_FUNC_NOT_EXIST = 'The method has not been registered.';
35const ERROR_MSG_INNER_ERROR = 'Inner Error.';
36
37let errMap = new Map();
38errMap.set(ERROR_CODE_INVALID_PARAM, ERROR_MSG_INVALID_PARAM);
39errMap.set(ERROR_CODE_FUNC_REGISTERED, ERROR_MSG_FUNC_REGISTERED);
40errMap.set(ERROR_CODE_FUNC_NOT_EXIST, ERROR_MSG_FUNC_NOT_EXIST);
41errMap.set(ERROR_CODE_INNER_ERROR, ERROR_MSG_INNER_ERROR);
42
43class BusinessError extends Error {
44  constructor(code) {
45    let msg = '';
46    if (errMap.has(code)) {
47      msg = errMap.get(code);
48    } else {
49      msg = ERROR_MSG_INNER_ERROR;
50    }
51    super(msg);
52    this.code = code;
53  }
54}
55
56class ThrowInvalidParamError extends Error {
57  constructor(msg) {
58    let message = ERROR_MSG_INVALID_PARAM + msg;
59    super(message);
60    this.code = ERROR_CODE_INVALID_PARAM;
61  }
62}
63
64class Callee extends rpc.RemoteObject {
65  constructor(des) {
66    if (typeof des === 'string') {
67      super(des);
68      this.callList = new Map();
69      this.startUpNewRule = false;
70      hilog.sLogI(domainID, TAG, 'Callee constructor is OK ' + typeof des);
71    } else {
72      hilog.sLogI(domainID, TAG, 'Callee constructor error, des is ' + typeof des);
73      return null;
74    }
75  }
76
77  setNewRuleFlag(flag) {
78    this.startUpNewRule = flag;
79  }
80
81  onRemoteMessageRequest(code, data, reply, option) {
82    hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest code [' + typeof code + ' ' + code + ']');
83    if (!this.StartUpRuleCheck()) {
84      return false;
85    }
86
87    if (typeof code !== 'number' || typeof data !== 'object' ||
88      typeof reply !== 'object' || typeof option !== 'object') {
89      hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest error, code is [' +
90        typeof code + '], data is [' + typeof data + '], reply is [' +
91        typeof reply + '], option is [' + typeof option + ']');
92      return false;
93    }
94
95    hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest code proc');
96    if (code === EVENT_CALL_NOTIFY) {
97      if (this.callList == null) {
98        hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest error, this.callList is nullptr');
99        return false;
100      }
101
102      let method = data.readString();
103      hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest method [' + method + ']');
104      let func = this.callList.get(method);
105      if (typeof func !== 'function') {
106        hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest error, get func is ' + typeof func);
107        return false;
108      }
109
110      let result = func(data);
111      if (typeof result === 'object' && result != null) {
112        reply.writeInt(REQUEST_SUCCESS);
113        reply.writeString(typeof result);
114        reply.writeParcelable(result);
115        hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest code proc Packed data');
116      } else {
117        reply.writeInt(REQUEST_FAILED);
118        reply.writeString(typeof result);
119        hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest error, retval is ' +
120          REQUEST_FAILED + ', type is ' + typeof result, REQUEST_FAILED, typeof result);
121      }
122    } else {
123      hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest error, code is ' + code);
124      return false;
125    }
126    hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest code proc success');
127    return true;
128  }
129
130  on(method, callback) {
131    if (typeof method !== 'string' || method === '' || typeof callback !== 'function') {
132      hilog.sLogI(domainID, TAG,
133        'Callee on error, method is [' + typeof method + '], typeof callback [' + typeof callback + ']');
134      throw new ThrowInvalidParamError('Parameter error: Failed to get method or callback.' +
135        'method must be a non-empty string, callback must be a function.');
136    }
137
138    if (this.callList == null) {
139      hilog.sLogI(domainID, TAG, 'Callee on error, this.callList is nullptr');
140      throw new BusinessError(ERROR_CODE_INNER_ERROR);
141    }
142
143    if (this.callList.has(method)) {
144      hilog.sLogI(domainID, TAG, 'Callee on error, [' + method + '] has registered');
145      throw new BusinessError(ERROR_CODE_FUNC_REGISTERED);
146    }
147
148    this.callList.set(method, callback);
149    hilog.sLogI(domainID, TAG, 'Callee on method [' + method + ']');
150  }
151
152  off(method) {
153    if (typeof method !== 'string' || method === '') {
154      hilog.sLogI(domainID, TAG, 'Callee off error, method is [' + typeof method + ']');
155      throw new ThrowInvalidParamError('Parameter error: Failed to get method, must be a string.');
156    }
157
158    if (this.callList == null) {
159      hilog.sLogI(domainID, TAG, 'Callee off error, this.callList is null');
160      throw new BusinessError(ERROR_CODE_INNER_ERROR);
161    }
162
163    if (!this.callList.has(method)) {
164      hilog.sLogI(domainID, TAG, 'Callee off error, this.callList not found ' + method);
165      throw new BusinessError(ERROR_CODE_FUNC_NOT_EXIST);
166    }
167
168    this.callList.delete(method);
169    hilog.sLogI(domainID, TAG, 'Callee off method [' + method + ']');
170  }
171
172  StartUpRuleCheck() {
173    if (this.startUpNewRule && rpc.IPCSkeleton.isLocalCalling()) {
174      hilog.sLogI(domainID, TAG, 'Use new start up rule, check caller permission.');
175      let accessManger = accessControl.createAtManager();
176      let accessTokenId = rpc.IPCSkeleton.getCallingTokenId();
177      let grantStatus =
178        accessManger.verifyAccessTokenSync(accessTokenId, PERMISSION_ABILITY_BACKGROUND_COMMUNICATION);
179      if (grantStatus === accessControl.GrantStatus.PERMISSION_DENIED) {
180        hilog.sLogI(domainID, TAG,
181          'Callee onRemoteMessageRequest error, the Caller does not have PERMISSION_ABILITY_BACKGROUND_COMMUNICATION');
182        return false;
183      }
184    }
185    return true;
186  }
187}
188
189export default Callee;
190