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