1 /*
2 * Copyright (c) 2021 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 #include "js_plugin_callback.h"
16
17 #include "hilog_wrapper.h"
18 #include "js_plugin_callback_mgr.h"
19 #include "js_plugin_util.h"
20 #include "js_plugin_want.h"
21
22 #include "core/components/plugin/plugin_component_manager.h"
23
24 namespace OHOS::Ace::Napi {
25 std::atomic_size_t JSPluginCallback::uuid_ = 0;
26 constexpr int ACE_ARGS_TWO = 2;
27 constexpr int ACE_ARGS_THREE = 3;
28 constexpr int ACE_ARGS_FOUR = 4;
29 constexpr int ACE_PARAM0 = 0;
30 constexpr int ACE_PARAM1 = 1;
31 constexpr int ACE_PARAM2 = 2;
32 constexpr int ACE_PARAM3 = 3;
33
operator ==(const AceJSPluginRequestParam & param) const34 bool AceJSPluginRequestParam::operator==(const AceJSPluginRequestParam& param) const
35 {
36 AppExecFwk::ElementName leftElement = want_.GetElement();
37 AppExecFwk::ElementName rightElement = param.want_.GetElement();
38 if (leftElement == rightElement) {
39 if (name_ == param.name_ && data_ == param.data_ && jsonPath_ == param.jsonPath_) {
40 return true;
41 }
42 }
43 return false;
44 }
45
operator !=(const AceJSPluginRequestParam & param) const46 bool AceJSPluginRequestParam::operator!=(const AceJSPluginRequestParam& param) const
47 {
48 return !operator==(param);
49 }
50
JSPluginCallback(CallBackType eventType,ACECallbackInfo & cbInfo)51 JSPluginCallback::JSPluginCallback(CallBackType eventType,
52 ACECallbackInfo& cbInfo) : eventType_(eventType)
53 {
54 uuid_++;
55 cbInfo_.env = cbInfo.env;
56 cbInfo_.callback = cbInfo.callback;
57 }
58
~JSPluginCallback()59 JSPluginCallback::~JSPluginCallback()
60 {
61 if (uuid_ > 0) {
62 uuid_--;
63 }
64 DestroyAllResource();
65 }
66
DestroyAllResource(void)67 void JSPluginCallback::DestroyAllResource(void)
68 {
69 if (cbInfo_.env != nullptr && cbInfo_.callback != nullptr) {
70 napi_delete_reference(cbInfo_.env, cbInfo_.callback);
71 }
72 cbInfo_.env = nullptr;
73 cbInfo_.callback = nullptr;
74 }
75
SetWant(const AAFwk::Want & want)76 void JSPluginCallback::SetWant(const AAFwk::Want& want)
77 {
78 want_ = want;
79 }
80
GetWant()81 AAFwk::Want& JSPluginCallback::GetWant()
82 {
83 return want_;
84 }
85
SetRequestParam(const std::shared_ptr<AceJSPluginRequestParam> & param)86 void JSPluginCallback::SetRequestParam(const std::shared_ptr<AceJSPluginRequestParam>& param)
87 {
88 requestParam_ = param;
89 }
90
GetID(void)91 size_t JSPluginCallback::GetID(void)
92 {
93 return uuid_;
94 }
95
SendRequestEventResult(napi_value jsObject)96 void JSPluginCallback::SendRequestEventResult(napi_value jsObject)
97 {
98 std::string strTemplate("");
99 std::string strDate("");
100 std::string strExtraData("");
101 napi_value jsTemplate = AceGetPropertyValueByPropertyName(cbInfo_.env, jsObject, "template", napi_string);
102 napi_value jsData = AceGetPropertyValueByPropertyName(cbInfo_.env, jsObject, "data", napi_object);
103 napi_value jsExtraData = AceGetPropertyValueByPropertyName(cbInfo_.env, jsObject, "extraData", napi_object);
104
105 if (jsTemplate != nullptr) {
106 strTemplate = AceUnwrapStringFromJS(cbInfo_.env, jsTemplate);
107 }
108
109 if (jsData != nullptr) {
110 AceKVObjectToString(cbInfo_.env, jsData, strDate);
111 }
112
113 if (jsExtraData != nullptr) {
114 AceKVObjectToString(cbInfo_.env, jsExtraData, strExtraData);
115 }
116 PluginComponentManager::GetInstance()->ReturnRequest(want_, strTemplate, strDate, strExtraData);
117 }
118
MakeCallbackParamForRequest(const PluginComponentTemplate & pluginTemplate,const std::string & data,const std::string & extraData)119 napi_value JSPluginCallback::MakeCallbackParamForRequest(
120 const PluginComponentTemplate& pluginTemplate, const std::string& data, const std::string& extraData)
121 {
122 napi_value jsObject = AceCreateJSObject(cbInfo_.env);
123 if (jsObject == nullptr) {
124 return nullptr;
125 }
126
127 std::string dataTmp("{}");
128 std::string extraDataTmp("{}");
129 if (!data.empty()) {
130 dataTmp = data;
131 }
132 if (!extraData.empty()) {
133 extraDataTmp = extraData;
134 }
135
136 napi_value jsPluginTemplate = MakePluginTemplateObject(pluginTemplate);
137 napi_value jsData = AceStringToKVObject(cbInfo_.env, dataTmp);
138 napi_value jsExtraData = AceStringToKVObject(cbInfo_.env, extraDataTmp);
139
140 if (jsData != nullptr) {
141 AceSetPropertyValueByPropertyName(cbInfo_.env, jsObject, "componentTemplate", jsPluginTemplate);
142 }
143 if (jsData != nullptr) {
144 AceSetPropertyValueByPropertyName(cbInfo_.env, jsObject, "data", jsData);
145 }
146 if (jsExtraData != nullptr) {
147 AceSetPropertyValueByPropertyName(cbInfo_.env, jsObject, "extraData", jsExtraData);
148 }
149 return jsObject;
150 }
151
MakePluginTemplateObject(const PluginComponentTemplate & pluginTemplate)152 napi_value JSPluginCallback::MakePluginTemplateObject(const PluginComponentTemplate& pluginTemplate)
153 {
154 HILOG_INFO("%{public}s called.", __func__);
155 napi_value jsPluginTemplate = AceCreateJSObject(cbInfo_.env);
156 if (jsPluginTemplate != nullptr) {
157 napi_value jsSource = AceWrapStringToJS(cbInfo_.env, pluginTemplate.GetSource());
158 napi_value jsAbility = AceWrapStringToJS(cbInfo_.env, pluginTemplate.GetAbility());
159
160 AceSetPropertyValueByPropertyName(cbInfo_.env, jsPluginTemplate, "source", jsSource);
161 AceSetPropertyValueByPropertyName(cbInfo_.env, jsPluginTemplate, "ability", jsAbility);
162 }
163 return jsPluginTemplate;
164 }
165
OnPushEventInner(const OnPluginUvWorkData * workData)166 void JSPluginCallback::OnPushEventInner(const OnPluginUvWorkData* workData)
167 {
168 napi_value jsCallback = nullptr;
169 napi_value undefined = nullptr;
170 napi_value jsResult = nullptr;
171 napi_value callbackParam[ACE_ARGS_FOUR] = {nullptr};
172 napi_handle_scope scope = nullptr;
173 std::string dataTmp("{}");
174 std::string extraDataTmp("{}");
175 if (!workData->data.empty()) {
176 dataTmp = workData->data;
177 }
178 if (!workData->extraData.empty()) {
179 extraDataTmp = workData->extraData;
180 }
181
182 napi_open_handle_scope(cbInfo_.env, &scope);
183 if (scope == nullptr) {
184 napi_close_handle_scope(cbInfo_.env, scope);
185 return;
186 }
187
188 PluginComponentTemplate componentTemplate;
189 componentTemplate.SetSource(workData->sourceName);
190 componentTemplate.SetAbility(workData->abilityName);
191
192 napi_open_handle_scope(cbInfo_.env, &scope);
193 if (scope == nullptr) {
194 napi_close_handle_scope(cbInfo_.env, scope);
195 return;
196 }
197 callbackParam[ACE_PARAM0] = AceWrapWant(cbInfo_.env, workData->want);
198 callbackParam[ACE_PARAM1] = MakePluginTemplateObject(componentTemplate);
199 callbackParam[ACE_PARAM2] = AceStringToKVObject(cbInfo_.env, dataTmp);
200 callbackParam[ACE_PARAM3] = AceStringToKVObject(cbInfo_.env, extraDataTmp);
201
202 napi_get_undefined(cbInfo_.env, &undefined);
203 napi_get_reference_value(cbInfo_.env, cbInfo_.callback, &jsCallback);
204 napi_call_function(cbInfo_.env, undefined, jsCallback, ACE_ARGS_FOUR, callbackParam, &jsResult);
205 napi_close_handle_scope(cbInfo_.env, scope);
206 }
207
OnPushEvent(const AAFwk::Want & want,const PluginComponentTemplate & pluginTemplate,const std::string & data,const std::string & extraData)208 void JSPluginCallback::OnPushEvent(const AAFwk::Want& want,
209 const PluginComponentTemplate& pluginTemplate, const std::string& data, const std::string& extraData)
210 {
211 HILOG_INFO("%{public}s called.", __func__);
212 if (cbInfo_.env == nullptr || cbInfo_.callback == nullptr) {
213 HILOG_INFO("%{public}s called, env or callback is null.", __func__);
214 return;
215 }
216
217 uvWorkData_.that = (void *)this;
218 uvWorkData_.want = want;
219 uvWorkData_.sourceName = pluginTemplate.GetSource();
220 uvWorkData_.abilityName = pluginTemplate.GetAbility();
221 uvWorkData_.data = data;
222 uvWorkData_.extraData = extraData;
223 OnPushEventInner(&uvWorkData_);
224 }
225
OnRequestEventInner(const OnPluginUvWorkData * workData)226 void JSPluginCallback::OnRequestEventInner(const OnPluginUvWorkData* workData)
227 {
228 napi_value jsCallback = nullptr;
229 napi_value undefined = nullptr;
230 napi_value jsResult = nullptr;
231 napi_handle_scope scope = nullptr;
232 std::string dataTmp("{}");
233 if (!workData->data.empty()) {
234 dataTmp = workData->data;
235 }
236
237 napi_open_handle_scope(cbInfo_.env, &scope);
238 if (scope == nullptr) {
239 napi_close_handle_scope(cbInfo_.env, scope);
240 return;
241 }
242 napi_value callbackParam[ACE_ARGS_THREE] = {nullptr};
243 callbackParam[ACE_PARAM0] = AceWrapWant(cbInfo_.env, workData->want);
244 callbackParam[ACE_PARAM1] = AceWrapStringToJS(cbInfo_.env, workData->name);
245 callbackParam[ACE_PARAM2] = AceStringToKVObject(cbInfo_.env, dataTmp);
246
247 napi_get_undefined(cbInfo_.env, &undefined);
248 napi_get_reference_value(cbInfo_.env, cbInfo_.callback, &jsCallback);
249 napi_call_function(cbInfo_.env, undefined, jsCallback, ACE_ARGS_THREE, callbackParam, &jsResult);
250
251 if (AceIsTypeForNapiValue(cbInfo_.env, jsResult, napi_object)) {
252 SendRequestEventResult(jsResult);
253 }
254 napi_close_handle_scope(cbInfo_.env, scope);
255 }
256
OnRequestEvent(const AAFwk::Want & want,const std::string & name,const std::string & data)257 void JSPluginCallback::OnRequestEvent(const AAFwk::Want& want, const std::string& name,
258 const std::string& data)
259 {
260 if (cbInfo_.env == nullptr || cbInfo_.callback == nullptr) {
261 HILOG_INFO("%{public}s called, env or callback is null.", __func__);
262 return;
263 }
264
265 uvWorkData_.that = (void *)this;
266 uvWorkData_.want = want;
267 uvWorkData_.data = data;
268 uvWorkData_.name = name;
269 OnRequestEventInner(&uvWorkData_);
270 }
271
OnRequestCallBackInner(const OnPluginUvWorkData * workData)272 void JSPluginCallback::OnRequestCallBackInner(const OnPluginUvWorkData* workData)
273 {
274 napi_value jsCallback = nullptr;
275 napi_value undefined = nullptr;
276 napi_value jsResult = nullptr;
277 napi_handle_scope scope = nullptr;
278 napi_open_handle_scope(cbInfo_.env, &scope);
279 if (scope == nullptr) {
280 napi_close_handle_scope(cbInfo_.env, scope);
281 return;
282 }
283 PluginComponentTemplate componentTemplate;
284 componentTemplate.SetSource(workData->sourceName);
285 componentTemplate.SetAbility(workData->abilityName);
286 napi_value callbackParam[ACE_ARGS_TWO] = {nullptr};
287
288 callbackParam[ACE_PARAM0] = AceGetCallbackErrorValue(cbInfo_.env, 0);
289 callbackParam[ACE_PARAM1] = MakeCallbackParamForRequest(componentTemplate, workData->data,
290 workData->extraData);
291
292 napi_get_undefined(cbInfo_.env, &undefined);
293 napi_get_reference_value(cbInfo_.env, cbInfo_.callback, &jsCallback);
294 napi_call_function(cbInfo_.env, undefined, jsCallback, ACE_ARGS_TWO, callbackParam, &jsResult);
295 napi_close_handle_scope(cbInfo_.env, scope);
296 }
297
OnRequestCallBack(const PluginComponentTemplate & pluginTemplate,const std::string & data,const std::string & extraData)298 void JSPluginCallback::OnRequestCallBack(const PluginComponentTemplate& pluginTemplate,
299 const std::string& data, const std::string& extraData)
300 {
301 HILOG_INFO("%{public}s called.", __func__);
302 JSPluginCallbackMgr::Instance().UnRegisterEvent(GetID());
303 if (cbInfo_.env == nullptr || cbInfo_.callback == nullptr) {
304 HILOG_INFO("%{public}s called, env or callback is null.", __func__);
305 return;
306 }
307
308 uvWorkData_.that = (void *)this;
309 uvWorkData_.sourceName = pluginTemplate.GetSource();
310 uvWorkData_.abilityName = pluginTemplate.GetAbility();
311 uvWorkData_.data = data;
312 uvWorkData_.extraData = extraData;
313 OnRequestCallBackInner(&uvWorkData_);
314 }
315
OnEventStrictEquals(CallBackType eventType,const AAFwk::Want & want,ACECallbackInfo & cbInfo)316 bool JSPluginCallback::OnEventStrictEquals(CallBackType eventType, const AAFwk::Want& want,
317 ACECallbackInfo& cbInfo)
318 {
319 if (eventType != eventType_) {
320 return false;
321 }
322 AppExecFwk::ElementName leftElement = want.GetElement();
323 AppExecFwk::ElementName rightElement = want_.GetElement();
324 if (leftElement == rightElement) {
325 return AceIsSameFuncFromJS(cbInfo, cbInfo_);
326 } else {
327 return false;
328 }
329 }
330
RequestStrictEquals(CallBackType eventType,const AAFwk::Want & want,ACECallbackInfo & cbInfo,const std::shared_ptr<AceJSPluginRequestParam> & param)331 bool JSPluginCallback::RequestStrictEquals(CallBackType eventType, const AAFwk::Want& want,
332 ACECallbackInfo& cbInfo, const std::shared_ptr<AceJSPluginRequestParam>& param)
333 {
334 if (eventType != eventType_) {
335 return false;
336 }
337 AppExecFwk::ElementName leftElement = want.GetElement();
338 AppExecFwk::ElementName rightElement = want_.GetElement();
339 if (!(leftElement == rightElement)) {
340 return false;
341 }
342 if (param == nullptr || requestParam_ == nullptr) {
343 return false;
344 }
345 if (*param != *requestParam_) {
346 return false;
347 }
348 return AceIsSameFuncFromJS(cbInfo, cbInfo_);
349 }
350 } // namespace OHOS::Ace::Napi
351