1/* 2 * Copyright (c) 2021-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 */ 15 16import worker from '@ohos.worker'; 17import Log from '../default/Log'; 18import BundleManager from '../default/abilitymanager/bundleManager'; 19import { Want } from 'ability/want'; 20import Constants, { ItemComponentData, obtainMsg, RootConfigInfo } from './common/Constants'; 21import ServiceExtensionContext from 'application/ServiceExtensionContext'; 22import PluginSourceLoaderPatch from './sourceloader/PluginSourceLoaderPatch' 23 24export interface PluginWorkerListener { 25 initFinish(): void; 26 onItemAdd(data: ItemComponentData): void; 27 onItemRemove(data: ItemComponentData): void; 28}; 29 30const TAG = 'PluginDataSourceAdapter'; 31 32export default class PluginDataSourceAdapter { 33 mContext: ServiceExtensionContext; 34 mWorker; 35 mName: string; 36 mListener: PluginWorkerListener; 37 mWant: Want; 38 mPluginSourceLoaderPatch: PluginSourceLoaderPatch; 39 mModuleName: string; 40 41 constructor(name: string, context: ServiceExtensionContext, listener: PluginWorkerListener, moduleName: string) { 42 Log.showDebug(TAG, `constructor, name: ${name}`); 43 this.mName = name; 44 this.mContext = context; 45 this.mListener = listener; 46 this.mModuleName = moduleName; 47 const WORKER_JS_URL = this.mModuleName + '/ets/workers/PluginDataSourceWorker.js'; 48 this.mWorker = new worker.Worker(WORKER_JS_URL, { 49 type: 'classic', 50 name: this.mName, 51 }); 52 53 this.mWorker.onmessage = this.onMessage.bind(this); 54 this.mWorker.onmessageerror = this.onMessageError.bind(this); 55 this.mWorker.onexit = this.onExit.bind(this); 56 this.mWorker.onerror = this.onError.bind(this); 57 } 58 59 setWant(want: Want): void{ 60 this.mWant = want; 61 } 62 63 initDataSource(configs: RootConfigInfo): void { 64 Log.showDebug(TAG, `name: ${this.mName}, initDataSource, configs: ${JSON.stringify(configs)}`); 65 this.mWorker.postMessage(obtainMsg(Constants.INIT_CONFIG, configs)); 66 if (configs.loaderConfig.PluginSourceLoader) { 67 this.mPluginSourceLoaderPatch = new PluginSourceLoaderPatch(this.mWant, this); 68 } 69 } 70 71 loadData(userId: number): void { 72 Log.showDebug(TAG, `name: ${this.mName}, loadData`); 73 this.mWorker.postMessage(obtainMsg(Constants.LOAD_DATA, userId)); 74 } 75 76 clearAll(): void { 77 Log.showDebug(TAG, `name: ${this.mName}, clearAll`); 78 this.mWorker.postMessage(obtainMsg(Constants.CLEAR_ALL, {})); 79 this.mPluginSourceLoaderPatch?.clearAll(); 80 } 81 82 onMessage(msg: { data }): void { 83 Log.showDebug(TAG, `name: ${this.mName}, onMessage, msg: ${JSON.stringify(msg)}`); 84 let data = msg.data; 85 switch (data.action) { 86 case Constants.INIT_FINISH: 87 this.onInitFinish(); 88 break; 89 case Constants.ADD_ITEM: 90 this.onItemAdd(data.data); 91 break; 92 case Constants.REMOVE_ITEM: 93 this.onItemRemove(data.data); 94 break; 95 case Constants.LOAD_PLUGIN_COMPONENT_DATA: 96 this.onLoadPluginComponentData(data.data).then(() => { 97 }).catch(err => { 98 }); 99 break; 100 default: 101 Log.showError(TAG, `name: ${this.mName}, unknown type: ${data.action}`); 102 } 103 } 104 105 onInitFinish(): void { 106 Log.showDebug(TAG, `name: ${this.mName}, onInitFinish`); 107 this.mListener.initFinish(); 108 } 109 110 async onItemAdd(itemData: ItemComponentData): Promise<void> { 111 Log.showDebug(TAG, `name: ${this.mName}, onItemAdd, itemData: ${JSON.stringify(itemData)}`); 112 itemData.label && (itemData.label = decodeURIComponent(itemData.label)); 113 if (itemData.label && itemData.iconUrl) { 114 this.mListener.onItemAdd(itemData); 115 return; 116 } 117 Promise.all([ 118 itemData.iconUrl ?? BundleManager.getMediaBase64({bundleName: itemData.bundleName, moduleName: itemData.moduleName, id: itemData.abilityIconId}), 119 itemData.label ?? BundleManager.getString({bundleName: itemData.bundleName, moduleName: itemData.moduleName, id: itemData.abilityLabelId}), 120 ]) 121 .then(([iconValue, labelValue]) => { 122 iconValue && (itemData.iconUrl = iconValue); 123 labelValue && (itemData.label = labelValue); 124 this.mListener.onItemAdd(itemData); 125 }) 126 .catch((err) => Log.showError(TAG, `name: ${this.mName}, Can't get bundle info, err: ${JSON.stringify(err)}`)); 127 } 128 129 onItemRemove(itemData: ItemComponentData): void { 130 Log.showDebug(TAG, `name: ${this.mName}, onItemRemove, itemData: ${JSON.stringify(itemData)}`); 131 this.mListener.onItemRemove(itemData); 132 } 133 134 async onLoadPluginComponentData(itemData: ItemComponentData): Promise<void> { 135 Log.showDebug(TAG, `name: ${this.mName}, onLoadPluginComponentData, itemData: ${JSON.stringify(itemData)}`); 136 let ret = await this.mPluginSourceLoaderPatch?.requestPluginComponentData(itemData); 137 this.mWorker.postMessage(obtainMsg(Constants.UPDATE_PLUGIN_COMPONENT_DATA, ret)); 138 } 139 140 async onUpdatePluginComponentData(pluginComponentData: ItemComponentData): Promise<void> { 141 Log.showDebug(TAG, `name: ${this.mName}, onUpdatePluginComponentData, pluginComponentData: ${JSON.stringify(pluginComponentData)}`); 142 this.mWorker.postMessage(obtainMsg(Constants.UPDATE_PLUGIN_COMPONENT_DATA, pluginComponentData)); 143 } 144 145 onMessageError(event): void { 146 Log.showDebug(TAG, `name: ${this.mName}, mWorker.onmessageerror, event: ${JSON.stringify(event)}`); 147 } 148 149 onExit(code: number): void { 150 Log.showDebug(TAG, `name: ${this.mName}, mWorker.onexit, code: ${code}`); 151 } 152 153 onError(err): void { 154 Log.showDebug(TAG, `name: ${this.mName}, mWorker.onerror, err: ${JSON.stringify(err)}`); 155 } 156} 157