1/* 2 * Copyright (c) 2022-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 */ 15let rpc = requireNapi('rpc'); 16 17const EVENT_CALL_NOTIFY = 1; 18const REQUEST_SUCCESS = 0; 19 20const ERROR_CODE_INVALID_PARAM = 401; 21const ERROR_CODE_CALLER_RELEASED = 16200001; 22const ERROR_CODE_CLAAEE_INVALID = 16200002; 23const ERROR_CODE_INNER_ERROR = 16000050; 24 25const ERROR_MSG_INVALID_PARAM = 'Invalid input parameter.'; 26const ERROR_MSG_CALLER_RELEASED = 'Caller released. The caller has been released.'; 27const ERROR_MSG_CLAAEE_INVALID = 'Callee invalid. The callee does not exist.'; 28const ERROR_MSG_INNER_ERROR = 'Inner Error.'; 29 30let errMap = new Map(); 31errMap.set(ERROR_CODE_INVALID_PARAM, ERROR_MSG_INVALID_PARAM); 32errMap.set(ERROR_CODE_CALLER_RELEASED, ERROR_MSG_CALLER_RELEASED); 33errMap.set(ERROR_CODE_CLAAEE_INVALID, ERROR_MSG_CLAAEE_INVALID); 34errMap.set(ERROR_CODE_INNER_ERROR, ERROR_MSG_INNER_ERROR); 35 36class BusinessError extends Error { 37 constructor(code) { 38 let msg = ''; 39 if (errMap.has(code)) { 40 msg = errMap.get(code); 41 } else { 42 msg = ERROR_MSG_INNER_ERROR; 43 } 44 super(msg); 45 this.code = code; 46 } 47} 48 49class Caller { 50 constructor(obj) { 51 console.log('Caller::constructor obj is ' + typeof obj); 52 this.__call_obj__ = obj; 53 this.releaseState = false; 54 } 55 56 call(method, data) { 57 return new Promise(async (resolve, reject) => { 58 const checkError = this.callCheck(method, data); 59 if (checkError != null) { 60 reject(checkError); 61 return; 62 } 63 64 console.log('Caller call msgData rpc.MessageSequence create'); 65 let msgData = this.buildMsgData(method, data); 66 let msgReply = rpc.MessageSequence.create(); 67 68 let retData = undefined; 69 try { 70 retData = await this.__call_obj__.callee.sendMessageRequest(EVENT_CALL_NOTIFY, msgData, msgReply, 71 rpc.MessageOption()); 72 console.log('Caller call msgData rpc.sendMessageRequest called'); 73 if (retData.errCode !== 0) { 74 msgData.reclaim(); 75 msgReply.reclaim(); 76 console.log('Caller call return errCode ' + retData.errCode); 77 reject(new BusinessError(retData.errCode)); 78 return; 79 } 80 } catch (e) { 81 console.log('Caller call msgData rpc.sendMessageRequest error ' + e); 82 } 83 84 try { 85 let retval = retData.reply.readInt(); 86 let str = retData.reply.readString(); 87 if (retval === REQUEST_SUCCESS && str === 'object') { 88 msgData.reclaim(); 89 msgReply.reclaim(); 90 } else { 91 console.log('Caller call retval is [' + retval + '], str [' + str + ']'); 92 msgData.reclaim(); 93 msgReply.reclaim(); 94 reject(new BusinessError(retval)); 95 return; 96 } 97 } catch (e) { 98 console.log('Caller call msgData sendMessageRequest retval error'); 99 reject(new BusinessError(ERROR_CODE_INNER_ERROR)); 100 return; 101 } 102 103 console.log('Caller call msgData sendMessageRequest end'); 104 resolve(undefined); 105 return; 106 }); 107 } 108 109 callWithResult(method, data) { 110 return new Promise(async (resolve, reject) => { 111 console.log('Caller callWithResult method [' + method + ']'); 112 const checkError = this.callCheck(method, data); 113 if (checkError != null) { 114 reject(checkError); 115 return; 116 } 117 118 console.log('Caller callWithResult msgData rpc.MessageSequence create'); 119 let msgData = this.buildMsgData(method, data); 120 let msgReply = rpc.MessageSequence.create(); 121 122 let reply = undefined; 123 let retData = undefined; 124 try { 125 retData = await this.__call_obj__.callee.sendMessageRequest(EVENT_CALL_NOTIFY, msgData, msgReply, 126 rpc.MessageOption()); 127 console.log('Caller callWithResult msgData rpc.sendMessageRequest called'); 128 if (retData.errCode !== 0) { 129 msgData.reclaim(); 130 msgReply.reclaim(); 131 console.log('Caller callWithResult return errCode ' + retData.errCode); 132 reject(new BusinessError(retData.errCode)); 133 return; 134 } 135 } catch (e) { 136 console.log('Caller call msgData rpc.MessageSequence error ' + e); 137 } 138 139 try { 140 let retval = retData.reply.readInt(); 141 let str = retData.reply.readString(); 142 if (retval === REQUEST_SUCCESS && str === 'object') { 143 msgData.reclaim(); 144 reply = retData.reply; 145 } else { 146 console.log('Caller callWithResult retval is [' + retval + '], str [' + str + ']'); 147 msgData.reclaim(); 148 msgReply.reclaim(); 149 reject(new BusinessError(retval)); 150 return; 151 } 152 } catch (e) { 153 console.log('Caller callWithResult msgData sendMessageRequest retval error'); 154 reject(new BusinessError(ERROR_CODE_INNER_ERROR)); 155 return; 156 } 157 158 console.log('Caller callWithResult msgData sendMessageRequest end'); 159 resolve(reply); 160 return; 161 }); 162 } 163 164 release() { 165 console.log('Caller release js called.'); 166 if (this.releaseState === true) { 167 console.log('Caller release remoteObj releaseState is true'); 168 throw new BusinessError(ERROR_CODE_CALLER_RELEASED); 169 } 170 171 if (this.__call_obj__.callee == null) { 172 console.log('Caller release call remoteObj is released'); 173 throw new BusinessError(ERROR_CODE_CLAAEE_INVALID); 174 } 175 176 this.releaseState = true; 177 this.__call_obj__.release(); 178 } 179 180 onRelease(callback) { 181 console.log('Caller onRelease jscallback called.'); 182 if (typeof callback !== 'function') { 183 console.log('Caller onRelease ' + typeof callback); 184 throw new BusinessError(ERROR_CODE_INVALID_PARAM); 185 } 186 187 if (this.releaseState === true) { 188 console.log('Caller onRelease remoteObj releaseState is true'); 189 throw new BusinessError(ERROR_CODE_CALLER_RELEASED); 190 } 191 192 this.__call_obj__.onRelease(callback); 193 } 194 195 onRemoteStateChange(callback) { 196 console.log('Caller onRemoteStateChange jscallback called.'); 197 if (typeof callback !== 'function') { 198 console.log('Caller onRemoteStateChange ' + typeof callback); 199 throw new BusinessError(ERROR_CODE_INVALID_PARAM); 200 } 201 202 if (this.releaseState === true) { 203 console.log('Caller onRemoteStateChange remoteObj releaseState is true'); 204 throw new BusinessError(ERROR_CODE_CALLER_RELEASED); 205 } 206 207 this.__call_obj__.onRemoteStateChange(callback); 208 } 209 210 on(type, callback) { 211 console.log('Caller onRelease jscallback called.'); 212 if (typeof type !== 'string' || type !== 'release') { 213 console.log( 214 'Caller onRelease error, input [type] is invalid.'); 215 throw new BusinessError(ERROR_CODE_INVALID_PARAM); 216 } 217 218 if (typeof callback !== 'function') { 219 console.log('Caller onRelease error ' + typeof callback); 220 throw new BusinessError(ERROR_CODE_INVALID_PARAM); 221 } 222 223 if (this.releaseState === true) { 224 console.log('Caller onRelease error, remoteObj releaseState is true'); 225 throw new BusinessError(ERROR_CODE_CALLER_RELEASED); 226 } 227 228 this.__call_obj__.onRelease(callback); 229 } 230 231 off(type, callback) { 232 if (typeof type !== 'string' || type !== 'release') { 233 console.log( 234 'Caller onRelease error, input [type] is invalid.'); 235 throw new BusinessError(ERROR_CODE_INVALID_PARAM); 236 } 237 238 if (callback && typeof callback !== 'function') { 239 console.log('Caller onRelease error ' + typeof callback); 240 throw new BusinessError(ERROR_CODE_INVALID_PARAM); 241 } 242 // Empty 243 } 244 245 callCheck(method, data) { 246 if (typeof method !== 'string' || typeof data !== 'object') { 247 console.log('Caller callCheck ' + typeof method + ' ' + typeof data); 248 return new BusinessError(ERROR_CODE_INVALID_PARAM); 249 } 250 251 if (method === '' || data == null) { 252 console.log('Caller callCheck ' + method + ', ' + data); 253 return new BusinessError(ERROR_CODE_INVALID_PARAM); 254 } 255 256 if (this.releaseState === true) { 257 console.log('Caller callCheck this.callee release'); 258 return new BusinessError(ERROR_CODE_CALLER_RELEASED); 259 } 260 261 if (this.__call_obj__.callee == null) { 262 console.log('Caller callCheck this.callee is nullptr'); 263 return new BusinessError(ERROR_CODE_CLAAEE_INVALID); 264 } 265 return null; 266 } 267 268 buildMsgData(method, data) { 269 let msgData = rpc.MessageSequence.create(); 270 msgData.writeString(method); 271 msgData.writeParcelable(data); 272 return msgData; 273 } 274} 275 276export default Caller; 277