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 ThrowInvalidParamError extends Error { 50 constructor(msg) { 51 let message = ERROR_MSG_INVALID_PARAM + msg; 52 super(message); 53 this.code = ERROR_CODE_INVALID_PARAM; 54 } 55} 56 57class Caller { 58 constructor(obj) { 59 console.log('Caller::constructor obj is ' + typeof obj); 60 this.__call_obj__ = obj; 61 this.releaseState = false; 62 } 63 64 call(method, data) { 65 return new Promise(async (resolve, reject) => { 66 const checkError = this.callCheck(method, data); 67 if (checkError != null) { 68 reject(checkError); 69 return; 70 } 71 72 console.log('Caller call msgData rpc.MessageSequence create'); 73 let msgData = this.buildMsgData(method, data); 74 let msgReply = rpc.MessageSequence.create(); 75 76 let retData = undefined; 77 try { 78 retData = await this.__call_obj__.callee.sendMessageRequest(EVENT_CALL_NOTIFY, msgData, msgReply, 79 rpc.MessageOption()); 80 console.log('Caller call msgData rpc.sendMessageRequest called'); 81 if (retData.errCode !== 0) { 82 msgData.reclaim(); 83 msgReply.reclaim(); 84 console.log('Caller call return errCode ' + retData.errCode); 85 reject(new BusinessError(retData.errCode)); 86 return; 87 } 88 } catch (e) { 89 console.log('Caller call msgData rpc.sendMessageRequest error ' + e); 90 } 91 92 try { 93 let retval = retData.reply.readInt(); 94 let str = retData.reply.readString(); 95 if (retval === REQUEST_SUCCESS && str === 'object') { 96 msgData.reclaim(); 97 msgReply.reclaim(); 98 } else { 99 console.log('Caller call retval is [' + retval + '], str [' + str + ']'); 100 msgData.reclaim(); 101 msgReply.reclaim(); 102 reject(new BusinessError(retval)); 103 return; 104 } 105 } catch (e) { 106 console.log('Caller call msgData sendMessageRequest retval error'); 107 msgData.reclaim(); 108 msgReply.reclaim(); 109 reject(new BusinessError(ERROR_CODE_INNER_ERROR)); 110 return; 111 } 112 113 console.log('Caller call msgData sendMessageRequest end'); 114 resolve(undefined); 115 return; 116 }); 117 } 118 119 callWithResult(method, data) { 120 return new Promise(async (resolve, reject) => { 121 console.log('Caller callWithResult method [' + method + ']'); 122 const checkError = this.callCheck(method, data); 123 if (checkError != null) { 124 reject(checkError); 125 return; 126 } 127 128 console.log('Caller callWithResult msgData rpc.MessageSequence create'); 129 let msgData = this.buildMsgData(method, data); 130 let msgReply = rpc.MessageSequence.create(); 131 132 let reply = undefined; 133 let retData = undefined; 134 try { 135 retData = await this.__call_obj__.callee.sendMessageRequest(EVENT_CALL_NOTIFY, msgData, msgReply, 136 rpc.MessageOption()); 137 console.log('Caller callWithResult msgData rpc.sendMessageRequest called'); 138 if (retData.errCode !== 0) { 139 msgData.reclaim(); 140 msgReply.reclaim(); 141 console.log('Caller callWithResult return errCode ' + retData.errCode); 142 reject(new BusinessError(retData.errCode)); 143 return; 144 } 145 } catch (e) { 146 console.log('Caller call msgData rpc.MessageSequence error ' + e); 147 } 148 149 try { 150 let retval = retData.reply.readInt(); 151 let str = retData.reply.readString(); 152 if (retval === REQUEST_SUCCESS && str === 'object') { 153 msgData.reclaim(); 154 reply = retData.reply; 155 } else { 156 console.log('Caller callWithResult retval is [' + retval + '], str [' + str + ']'); 157 msgData.reclaim(); 158 msgReply.reclaim(); 159 reject(new BusinessError(retval)); 160 return; 161 } 162 } catch (e) { 163 console.log('Caller callWithResult msgData sendMessageRequest retval error'); 164 msgData.reclaim(); 165 msgReply.reclaim(); 166 reject(new BusinessError(ERROR_CODE_INNER_ERROR)); 167 return; 168 } 169 170 console.log('Caller callWithResult msgData sendMessageRequest end'); 171 resolve(reply); 172 return; 173 }); 174 } 175 176 release() { 177 console.log('Caller release js called.'); 178 if (this.releaseState === true) { 179 console.log('Caller release remoteObj releaseState is true'); 180 throw new BusinessError(ERROR_CODE_CALLER_RELEASED); 181 } 182 183 if (this.__call_obj__.callee == null) { 184 console.log('Caller release call remoteObj is released'); 185 throw new BusinessError(ERROR_CODE_CLAAEE_INVALID); 186 } 187 188 this.releaseState = true; 189 this.__call_obj__.release(); 190 } 191 192 onRelease(callback) { 193 console.log('Caller onRelease jscallback called.'); 194 if (typeof callback !== 'function') { 195 console.log('Caller onRelease ' + typeof callback); 196 throw new ThrowInvalidParamError('Parameter error: Failed to get callback, must be a function.'); 197 } 198 199 if (this.releaseState === true) { 200 console.log('Caller onRelease remoteObj releaseState is true'); 201 throw new BusinessError(ERROR_CODE_CALLER_RELEASED); 202 } 203 204 this.__call_obj__.onRelease(callback); 205 } 206 207 onRemoteStateChange(callback) { 208 console.log('Caller onRemoteStateChange jscallback called.'); 209 if (typeof callback !== 'function') { 210 console.log('Caller onRemoteStateChange ' + typeof callback); 211 throw new ThrowInvalidParamError('Parameter error: Failed to get callback, must be a function.'); 212 } 213 214 if (this.releaseState === true) { 215 console.log('Caller onRemoteStateChange remoteObj releaseState is true'); 216 throw new BusinessError(ERROR_CODE_CALLER_RELEASED); 217 } 218 219 this.__call_obj__.onRemoteStateChange(callback); 220 } 221 222 on(type, callback) { 223 console.log('Caller onRelease jscallback called.'); 224 if (typeof type !== 'string' || type !== 'release') { 225 console.log( 226 'Caller onRelease error, input [type] is invalid.'); 227 throw new ThrowInvalidParamError('Parameter error: Failed to get type, must be string type release.'); 228 } 229 230 if (typeof callback !== 'function') { 231 console.log('Caller onRelease error ' + typeof callback); 232 throw new ThrowInvalidParamError('Parameter error: Failed to get callback, must be a function.'); 233 } 234 235 if (this.releaseState === true) { 236 console.log('Caller onRelease error, remoteObj releaseState is true'); 237 throw new BusinessError(ERROR_CODE_CALLER_RELEASED); 238 } 239 240 this.__call_obj__.onRelease(callback); 241 } 242 243 off(type, callback) { 244 if (typeof type !== 'string' || type !== 'release') { 245 console.log( 246 'Caller onRelease error, input [type] is invalid.'); 247 throw new ThrowInvalidParamError('Parameter error: Failed to get type, must be string type release.'); 248 } 249 250 if (callback && typeof callback !== 'function') { 251 console.log('Caller onRelease error ' + typeof callback); 252 throw new ThrowInvalidParamError('Parameter error: Failed to get callback, must be a function.'); 253 } 254 // Empty 255 } 256 257 callCheck(method, data) { 258 if (typeof method !== 'string' || typeof data !== 'object') { 259 console.log('Caller callCheck ' + typeof method + ' ' + typeof data); 260 return new ThrowInvalidParamError('Parameter error: Failed to get method or data, ' + 261 'method must be a string, data must be a rpc.Parcelable'); 262 } 263 264 if (method === '' || data == null) { 265 console.log('Caller callCheck ' + method + ', ' + data); 266 return new ThrowInvalidParamError('Parameter error: method or data is empty, Please check it.'); 267 } 268 269 if (this.releaseState === true) { 270 console.log('Caller callCheck this.callee release'); 271 return new BusinessError(ERROR_CODE_CALLER_RELEASED); 272 } 273 274 if (this.__call_obj__.callee == null) { 275 console.log('Caller callCheck this.callee is nullptr'); 276 return new BusinessError(ERROR_CODE_CLAAEE_INVALID); 277 } 278 return null; 279 } 280 281 buildMsgData(method, data) { 282 let msgData = rpc.MessageSequence.create(); 283 msgData.writeString(method); 284 msgData.writeParcelable(data); 285 return msgData; 286 } 287} 288 289export default Caller; 290