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