* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
let rpc = requireNapi('rpc');
let accessControl = requireNapi('abilityAccessCtrl');
let hilog = requireNapi('hilog');
let domainID = 0xD001320;
let TAG = 'JSENV';
const EVENT_CALL_NOTIFY = 1;
const REQUEST_SUCCESS = 0;
const REQUEST_FAILED = 1;
const PERMISSION_ABILITY_BACKGROUND_COMMUNICATION = 'ohos.permission.ABILITY_BACKGROUND_COMMUNICATION';
const ERROR_CODE_INVALID_PARAM = 401;
const ERROR_CODE_FUNC_REGISTERED = 16200004;
const ERROR_CODE_FUNC_NOT_EXIST = 16200005;
const ERROR_CODE_INNER_ERROR = 16000050;
const ERROR_MSG_INVALID_PARAM = 'Invalid input parameter.';
const ERROR_MSG_FUNC_REGISTERED = 'Method registered. The method has registered.';
const ERROR_MSG_FUNC_NOT_EXIST = 'The method has not been registered.';
const ERROR_MSG_INNER_ERROR = 'Inner Error.';
let errMap = new Map();
errMap.set(ERROR_CODE_INVALID_PARAM, ERROR_MSG_INVALID_PARAM);
errMap.set(ERROR_CODE_FUNC_REGISTERED, ERROR_MSG_FUNC_REGISTERED);
errMap.set(ERROR_CODE_FUNC_NOT_EXIST, ERROR_MSG_FUNC_NOT_EXIST);
errMap.set(ERROR_CODE_INNER_ERROR, ERROR_MSG_INNER_ERROR);
class BusinessError extends Error {
constructor(code) {
let msg = '';
if (errMap.has(code)) {
msg = errMap.get(code);
} else {
msg = ERROR_MSG_INNER_ERROR;
}
super(msg);
this.code = code;
}
}
class ThrowInvalidParamError extends Error {
constructor(msg) {
let message = ERROR_MSG_INVALID_PARAM + msg;
super(message);
this.code = ERROR_CODE_INVALID_PARAM;
}
}
class InnerCodeError extends Error {
constructor(msg) {
let message = ERROR_MSG_INNER_ERROR + ' ' + msg;
super(message);
this.code = ERROR_CODE_INNER_ERROR;
}
}
class Callee extends rpc.RemoteObject {
constructor(des) {
if (typeof des === 'string') {
super(des);
this.callList = new Map();
this.startUpNewRule = false;
hilog.sLogI(domainID, TAG, 'Callee constructor is OK ' + typeof des);
} else {
hilog.sLogI(domainID, TAG, 'Callee constructor error, des is ' + typeof des);
return null;
}
}
setNewRuleFlag(flag) {
this.startUpNewRule = flag;
}
onRemoteMessageRequest(code, data, reply, option) {
hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest code [' + typeof code + ' ' + code + ']');
if (!this.StartUpRuleCheck()) {
return false;
}
if (typeof code !== 'number' || typeof data !== 'object' ||
typeof reply !== 'object' || typeof option !== 'object') {
hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest error, code is [' +
typeof code + '], data is [' + typeof data + '], reply is [' +
typeof reply + '], option is [' + typeof option + ']');
return false;
}
hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest code proc');
if (code === EVENT_CALL_NOTIFY) {
if (this.callList == null) {
hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest error, this.callList is nullptr');
return false;
}
let method = data.readString();
hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest method [' + method + ']');
let func = this.callList.get(method);
if (typeof func !== 'function') {
hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest error, get func is ' + typeof func);
return false;
}
let result = func(data);
if (typeof result === 'object' && result != null) {
reply.writeInt(REQUEST_SUCCESS);
reply.writeString(typeof result);
reply.writeParcelable(result);
hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest code proc Packed data');
} else {
reply.writeInt(REQUEST_FAILED);
reply.writeString(typeof result);
hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest error, retval is ' +
REQUEST_FAILED + ', type is ' + typeof result, REQUEST_FAILED, typeof result);
}
} else {
hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest error, code is ' + code);
return false;
}
hilog.sLogI(domainID, TAG, 'Callee onRemoteMessageRequest code proc success');
return true;
}
on(method, callback) {
if (typeof method !== 'string' || method === '' || typeof callback !== 'function') {
hilog.sLogI(domainID, TAG,
'Callee on error, method is [' + typeof method + '], typeof callback [' + typeof callback + ']');
throw new ThrowInvalidParamError('Parameter error: Failed to get method or callback.' +
'method must be a non-empty string, callback must be a function.');
}
if (this.callList == null) {
hilog.sLogI(domainID, TAG, 'Callee on error, this.callList is nullptr');
throw new InnerCodeError('Inner data has not been initialized.');
}
if (this.callList.has(method)) {
hilog.sLogI(domainID, TAG, 'Callee on error, [' + method + '] has registered');
throw new BusinessError(ERROR_CODE_FUNC_REGISTERED);
}
this.callList.set(method, callback);
hilog.sLogI(domainID, TAG, 'Callee on method [' + method + ']');
}
off(method) {
if (typeof method !== 'string' || method === '') {
hilog.sLogI(domainID, TAG, 'Callee off error, method is [' + typeof method + ']');
throw new ThrowInvalidParamError('Parameter error: Failed to get method, must be a string.');
}
if (this.callList == null) {
hilog.sLogI(domainID, TAG, 'Callee off error, this.callList is null');
throw new InnerCodeError('Inner data has not been initialized.');
}
if (!this.callList.has(method)) {
hilog.sLogI(domainID, TAG, 'Callee off error, this.callList not found ' + method);
throw new BusinessError(ERROR_CODE_FUNC_NOT_EXIST);
}
this.callList.delete(method);
hilog.sLogI(domainID, TAG, 'Callee off method [' + method + ']');
}
StartUpRuleCheck() {
if (this.startUpNewRule && rpc.IPCSkeleton.isLocalCalling()) {
hilog.sLogI(domainID, TAG, 'Use new start up rule, check caller permission.');
let accessManger = accessControl.createAtManager();
let accessTokenId = rpc.IPCSkeleton.getCallingTokenId();
let grantStatus =
accessManger.verifyAccessTokenSync(accessTokenId, PERMISSION_ABILITY_BACKGROUND_COMMUNICATION);
if (grantStatus === accessControl.GrantStatus.PERMISSION_DENIED) {
hilog.sLogI(domainID, TAG,
'Callee onRemoteMessageRequest error, the Caller does not have PERMISSION_ABILITY_BACKGROUND_COMMUNICATION');
return false;
}
}
return true;
}
}
export default Callee;