1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19/* 20 * 2021.01.08 - The function 'standardization' is simpler and more accurate. 21 * And extend function 'send' to fit framework. 22 * Copyright (c) 2021 Huawei Device Co., Ltd. 23 */ 24 25import { 26 Log, 27 typof, 28 bufferToBase64 29} from '../../../utils/index'; 30import CallbackManager from './CallbackManager'; 31 32type OptionsType = Partial<Record<'action' | 'module' | 'method' | 'ref', string>> 33 34/** 35 * <p>Tasks processing center.</p> 36 * <p>Instructs the Native module to perform operations based on the message sent by the listener.</p> 37 * <p>Then the Native module invokes the callNative() callback function in sendTasks()<br> 38 * to send the message to the Native module.</p> 39 */ 40export class TaskCenter { 41 public instanceId: string; 42 public callbackManager: CallbackManager; 43 44 constructor(id: string) { 45 this.instanceId = id; 46 this.callbackManager = new CallbackManager(id); 47 } 48 49 /** 50 * Execute the consume() function from callbackManager class. 51 * @param {number} callbackId - Callback id. 52 * @param {Object} data - Data that needed. 53 * @param {boolean} ifKeepAlive - If keepAlive is false, delete this callback. 54 * @return {*} 55 */ 56 public consumeCallback(callbackId: number, data: object, ifKeepAlive: boolean): any | Error { 57 return this.callbackManager.consume(callbackId, data, ifKeepAlive); 58 } 59 60 /** 61 * Execute the close() function from callbackManager class. 62 * @param {number} callbackId - Callback id. 63 */ 64 public destroyCallback(): void { 65 return this.callbackManager.destroy(); 66 } 67 68 /** 69 * Execute the remove() function from callbackManager class. 70 * @param {number} callbackId - Callback id. 71 */ 72 public removeCallback(callbackId: number): void { 73 this.callbackManager.remove(callbackId); 74 } 75 76 /** 77 * Execute the isEmpty() function from callbackManager class. 78 * @param {number} callbackId - Callback id. 79 * @return {boolean} If callbacklist object is empty, return true. Otherwise return false. 80 */ 81 public callbackIsEmpty(): boolean { 82 return this.callbackManager.isEmpty(); 83 } 84 85 /** 86 * Normalize args. 87 * @param {*} v - Original args. 88 * @return {*} - Normalized args. 89 */ 90 public normalizePrimitive(v: any): any { 91 const type = typof(v); 92 93 switch (type) { 94 case 'undefined': 95 case 'null': 96 return ''; 97 98 case 'regexp': 99 return v.toString(); 100 case 'date': 101 return v.toISOString(); 102 103 case 'number': 104 case 'string': 105 case 'boolean': 106 case 'array': 107 case 'object': 108 return v; 109 110 case 'arraybuffer': 111 return { 112 '@type': 'binary', 113 dataType: type, 114 base64: bufferToBase64(v) 115 }; 116 117 case 'int8array': 118 case 'uint8array': 119 case 'uint8clampedarray': 120 case 'int16array': 121 case 'uint16array': 122 case 'int32array': 123 case 'uint32array': 124 case 'float32array': 125 case 'float64array': 126 return { 127 '@type': 'binary', 128 dataType: type, 129 base64: bufferToBase64(v.buffer) 130 }; 131 132 default: 133 return JSON.stringify(v); 134 } 135 } 136 137 /** 138 * Standardizing a value. Specially, if the value is a function, generate a function id. 139 * @param {*} arg - Any type. 140 * @return {*} 141 */ 142 public standardization(arg: any): any { 143 const type = typof(arg); 144 if (type === 'object') { 145 const ans = {}; 146 Object.keys(arg).forEach(key => { 147 ans[key] = this.standardization(arg[key]); 148 }); 149 return ans; 150 } else if (type === 'function') { 151 return this.callbackManager.add(arg).toString(); 152 } else if (type === 'array') { 153 return arg.map(i => this.standardization(i)); 154 } else { 155 return this.normalizePrimitive(arg); 156 } 157 } 158 159 /** 160 * Instruct the Native module to perform operations based on the message sent by the listener. 161 * @param {string} type - Such as dom, module and component. 162 * @param {OptionsType} options - Include action, module and method. 163 * @param {*} args - Args of a Vm. 164 */ 165 public send(type: string, options: OptionsType, args: any): any { 166 const { 167 action, 168 module, 169 method 170 } = options; 171 if (type !== 'dom') { 172 args = args.map(arg => this.standardization(arg)); 173 } 174 switch (type) { 175 case 'dom': 176 if (typeof ace !== 'undefined' && 177 typeof ace.domCreateBody !== 'undefined' && 178 typeof ace.domAddElement !== 'undefined') { 179 if (action === 'createBody') { 180 ace.domCreateBody( 181 0, 182 args[0].type, 183 args[0].attr, 184 args[0].style, 185 args[0].event 186 ); 187 } else if (action === 'addElement') { 188 ace.domAddElement( 189 args[0], 190 args[1].ref, 191 args[1].type, 192 args[1].attr, 193 args[1].style, 194 args[1].event, 195 args[1].customComponent, 196 args[2], 197 this.instanceId 198 ); 199 } else if (action === 'updateAttrs') { 200 ace.updateElementAttrs( 201 args[0], 202 args[1], 203 this.instanceId 204 ); 205 } else if (action === 'updateStyle') { 206 ace.updateElementStyles( 207 args[0], 208 args[1], 209 this.instanceId 210 ); 211 } else if (action === 'createFinish') { 212 ace.onCreateFinish(); 213 return; 214 } else if (action === 'updateFinish') { 215 ace.onUpdateFinish(); 216 return; 217 } else if (action === 'removeElement') { 218 ace.removeElement( 219 args[0], 220 this.instanceId 221 ); 222 } else { 223 Log.error( 224 'TaskCenter.js: send() unsupported action. IGNORING!' 225 ); 226 } 227 return; 228 } else { 229 Log.error( 230 'TaskCenter.js: attempting acev1 method for calling native' 231 ); 232 return; 233 } 234 235 case 'module': 236 switch (module) { 237 case 'system.fetch': 238 if (method === 'fetch') { 239 Log.error( 240 'TaskCenter.js: send: module system.fetch. calling ace.fetch.' 241 ); 242 ace.onFetchRequest(args[1], JSON.stringify(args)); 243 return; 244 } else { 245 Log.error( 246 'TaskCenter.js: send: module system.fetch. unrecognized method. Ignoring.' 247 ); 248 } 249 break; 250 case 'system.device': 251 return ace.callNative(JSON.stringify(options), args[args.length - 1]); 252 case 'system.router': 253 return ace.callNative(JSON.stringify(options), JSON.stringify(args[0])); 254 case 'system.prompt': 255 return ace.callNative(JSON.stringify(options), JSON.stringify(args[0])); 256 case 'system.app': 257 return ace.callNative(JSON.stringify(options), args); 258 case 'system.configuration': 259 return ace.callNative(JSON.stringify(options), JSON.stringify(args[0])); 260 case 'system.grid': 261 return ace.callNative(JSON.stringify(options), args); 262 case 'internal.jsResult': 263 return ace.callNative(JSON.stringify(options), args); 264 case 'timer': 265 return ace.callNative(JSON.stringify(options), args); 266 case 'system.offscreenCanvas': 267 return ace.callNative(JSON.stringify(options), JSON.stringify(args[0])); 268 case 'system.image': 269 return ace.callNative(JSON.stringify(options), JSON.stringify(args[0])); 270 case 'system.mediaquery': 271 return ace.callNative(JSON.stringify(options), args); 272 case 'animation': 273 return ace.callNative(JSON.stringify(options), args[0]); 274 case 'system.resource': 275 return ace.callNative(JSON.stringify(options), args); 276 case 'ohos.animator': 277 return ace.callNative(JSON.stringify(options), JSON.stringify(args[0])); 278 default: 279 break; 280 } 281 break; 282 283 case 'component': 284 return ace.callComponent(options.ref, method, JSON.stringify(args)); 285 default: 286 break; 287 } 288 } 289} 290