• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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