1 /*
2  * Copyright (c) 2021-2024 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 
16 #include "form_runtime/js_form_extension.h"
17 
18 #include "ability_info.h"
19 #include "connection_manager.h"
20 #include "form_provider_data.h"
21 #include "form_runtime/form_extension_provider_client.h"
22 #include "form_runtime/js_form_extension_context.h"
23 #include "hilog_tag_wrapper.h"
24 #include "js_extension_context.h"
25 #include "js_runtime.h"
26 #include "js_runtime_utils.h"
27 #include "napi/native_api.h"
28 #include "napi/native_node_api.h"
29 #include "napi_common_configuration.h"
30 #include "napi_common_util.h"
31 #include "napi_common_want.h"
32 #include <type_traits>
33 #include <vector>
34 
35 namespace OHOS {
36 namespace AbilityRuntime {
37 using namespace OHOS::AppExecFwk;
38 const int ON_EVENT_PARAMS_SIZE = 2;
39 const int ARGC_TWO = 2;
40 
AttachFormExtensionContext(napi_env env,void * value,void *)41 napi_value AttachFormExtensionContext(napi_env env, void* value, void*)
42 {
43     TAG_LOGI(AAFwkTag::FORM_EXT, "call");
44     if (value == nullptr) {
45         TAG_LOGW(AAFwkTag::FORM_EXT, "null value ");
46         return nullptr;
47     }
48     auto ptr = reinterpret_cast<std::weak_ptr<FormExtensionContext>*>(value)->lock();
49     if (ptr == nullptr) {
50         TAG_LOGW(AAFwkTag::FORM_EXT, "null context");
51         return nullptr;
52     }
53     napi_value object = CreateJsFormExtensionContext(env, ptr);
54     auto sysModule = JsRuntime::LoadSystemModuleByEngine(env,
55         "application.FormExtensionContext", &object, 1);
56     if (sysModule == nullptr) {
57         TAG_LOGW(AAFwkTag::FORM_EXT, "load module failed");
58         return nullptr;
59     }
60     auto contextObj = sysModule->GetNapiValue();
61     napi_coerce_to_native_binding_object(
62         env, contextObj, DetachCallbackFunc, AttachFormExtensionContext, value, nullptr);
63     auto workContext = new (std::nothrow) std::weak_ptr<FormExtensionContext>(ptr);
64     napi_wrap(env, contextObj, workContext,
65         [](napi_env, void * data, void *) {
66             TAG_LOGI(AAFwkTag::FORM_EXT, "Finalizer for weak_ptr form extension context is called");
67             delete static_cast<std::weak_ptr<FormExtensionContext> *>(data);
68         },
69         nullptr, nullptr);
70     return contextObj;
71 }
72 
Create(const std::unique_ptr<Runtime> & runtime)73 JsFormExtension* JsFormExtension::Create(const std::unique_ptr<Runtime>& runtime)
74 {
75     TAG_LOGI(AAFwkTag::FORM_EXT, "call");
76     return new JsFormExtension(static_cast<JsRuntime&>(*runtime));
77 }
78 
JsFormExtension(JsRuntime & jsRuntime)79 JsFormExtension::JsFormExtension(JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {}
~JsFormExtension()80 JsFormExtension::~JsFormExtension()
81 {
82     TAG_LOGD(AAFwkTag::FORM_EXT, "destructor");
83     auto context = GetContext();
84     if (context) {
85         context->Unbind();
86     }
87 
88     jsRuntime_.FreeNativeReference(std::move(jsObj_));
89     jsRuntime_.FreeNativeReference(std::move(shellContextRef_));
90 }
91 
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)92 void JsFormExtension::Init(const std::shared_ptr<AbilityLocalRecord> &record,
93     const std::shared_ptr<OHOSApplication> &application,
94     std::shared_ptr<AbilityHandler> &handler,
95     const sptr<IRemoteObject> &token)
96 {
97     TAG_LOGD(AAFwkTag::FORM_EXT, "call");
98     FormExtension::Init(record, application, handler, token);
99     std::string srcPath;
100     GetSrcPath(srcPath);
101     if (srcPath.empty()) {
102         TAG_LOGE(AAFwkTag::FORM_EXT, "get srcPath failed");
103         return;
104     }
105 
106     std::string moduleName(Extension::abilityInfo_->moduleName);
107     moduleName.append("::").append(abilityInfo_->name);
108     TAG_LOGD(AAFwkTag::FORM_EXT, "moduleName:%{public}s,srcPath:%{public}s,"
109         "compileMode :%{public}d", moduleName.c_str(), srcPath.c_str(), abilityInfo_->compileMode);
110     HandleScope handleScope(jsRuntime_);
111     auto env = jsRuntime_.GetNapiEnv();
112 
113     jsObj_ = jsRuntime_.LoadModule(
114         moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == CompileMode::ES_MODULE);
115     if (jsObj_ == nullptr) {
116         TAG_LOGE(AAFwkTag::FORM_EXT, "null jsObj");
117         return;
118     }
119 
120     napi_value obj = jsObj_->GetNapiValue();
121     if (!CheckTypeForNapiValue(env, obj, napi_object)) {
122         TAG_LOGE(AAFwkTag::FORM_EXT, "get JsFormExtension error");
123         return;
124     }
125 
126     BindContext(env, obj);
127 }
128 
BindContext(napi_env env,napi_value obj)129 void JsFormExtension::BindContext(napi_env env, napi_value obj)
130 {
131     auto context = GetContext();
132     if (context == nullptr) {
133         TAG_LOGE(AAFwkTag::FORM_EXT, "get context error");
134         return;
135     }
136     TAG_LOGD(AAFwkTag::FORM_EXT, "call");
137     napi_value contextObj = CreateJsFormExtensionContext(env, context);
138     shellContextRef_ = JsRuntime::LoadSystemModuleByEngine(env, "application.FormExtensionContext", &contextObj, 1);
139     if (shellContextRef_ == nullptr) {
140         TAG_LOGE(AAFwkTag::FORM_EXT, "load module failed");
141         return;
142     }
143     contextObj = shellContextRef_->GetNapiValue();
144     if (!CheckTypeForNapiValue(env, contextObj, napi_object)) {
145         TAG_LOGE(AAFwkTag::FORM_EXT, "get context failed");
146         return;
147     }
148     auto workContext = new (std::nothrow) std::weak_ptr<FormExtensionContext>(context);
149     napi_coerce_to_native_binding_object(
150         env, contextObj, DetachCallbackFunc, AttachFormExtensionContext, workContext, nullptr);
151     context->Bind(jsRuntime_, shellContextRef_.get());
152     napi_set_named_property(env, obj, "context", contextObj);
153 
154     napi_wrap(env, contextObj, workContext,
155         [](napi_env, void* data, void*) {
156             TAG_LOGI(AAFwkTag::FORM_EXT, "Finalizer for weak_ptr form extension context is called");
157             delete static_cast<std::weak_ptr<FormExtensionContext>*>(data);
158         },
159         nullptr, nullptr);
160 
161     TAG_LOGD(AAFwkTag::FORM_EXT, "ok");
162 }
163 
OnCreate(const OHOS::AAFwk::Want & want)164 OHOS::AppExecFwk::FormProviderInfo JsFormExtension::OnCreate(const OHOS::AAFwk::Want& want)
165 {
166     TAG_LOGI(AAFwkTag::FORM_EXT, "call");
167     HandleScope handleScope(jsRuntime_);
168     napi_env env = jsRuntime_.GetNapiEnv();
169     napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
170     napi_value argv[] = { napiWant };
171     napi_value nativeResult = CallObjectMethod("onAddForm", "onCreate", argv, 1);
172 
173     OHOS::AppExecFwk::FormProviderInfo formProviderInfo;
174     if (!CheckTypeForNapiValue(env, nativeResult, napi_object)) {
175         TAG_LOGE(AAFwkTag::FORM_EXT, "nativeResult null");
176         return formProviderInfo;
177     }
178 
179     napi_value nativeDataValue = nullptr;
180     napi_get_named_property(env, nativeResult, "data", &nativeDataValue);
181     if (nativeDataValue == nullptr) {
182         TAG_LOGE(AAFwkTag::FORM_EXT, "nativeResult null");
183         return formProviderInfo;
184     }
185     std::string formDataStr;
186     if (!ConvertFromJsValue(env, nativeDataValue, formDataStr)) {
187         TAG_LOGE(AAFwkTag::FORM_EXT, "Convert formDataStr failed");
188         return formProviderInfo;
189     }
190     AppExecFwk::FormProviderData formData = AppExecFwk::FormProviderData(formDataStr);
191     formProviderInfo.SetFormData(formData);
192 
193     napi_value nativeProxies = nullptr;
194     napi_get_named_property(env, nativeResult, "proxies", &nativeProxies);
195     std::vector<FormDataProxy> formDataProxies;
196     if (nativeProxies != nullptr && !ConvertFromDataProxies(env, nativeProxies, formDataProxies)) {
197         TAG_LOGW(AAFwkTag::FORM_EXT, "Convert formDataProxies failed");
198         return formProviderInfo;
199     }
200     formProviderInfo.SetFormDataProxies(formDataProxies);
201     TAG_LOGI(AAFwkTag::FORM_EXT, "ok");
202     return formProviderInfo;
203 }
204 
OnDestroy(const int64_t formId)205 void JsFormExtension::OnDestroy(const int64_t formId)
206 {
207     TAG_LOGI(AAFwkTag::FORM_EXT, "formId: %{public}" PRId64, formId);
208     FormExtension::OnDestroy(formId);
209 
210     HandleScope handleScope(jsRuntime_);
211     napi_env env = jsRuntime_.GetNapiEnv();
212     // wrap formId
213     napi_value napiFormId = nullptr;
214     napi_create_string_utf8(env, std::to_string(formId).c_str(), NAPI_AUTO_LENGTH,
215         &napiFormId);
216     napi_value argv[] = {napiFormId};
217     CallObjectMethod("onRemoveForm", "onDestroy", argv, 1);
218 }
219 
OnStop()220 void JsFormExtension::OnStop()
221 {
222     TAG_LOGI(AAFwkTag::FORM_EXT, "call");
223     CallObjectMethod("onStop", nullptr, nullptr, 0);
224     bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken());
225     if (ret) {
226         ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid());
227         TAG_LOGI(AAFwkTag::FORM_EXT, "disconnected failed");
228     }
229 }
230 
OnEvent(const int64_t formId,const std::string & message)231 void JsFormExtension::OnEvent(const int64_t formId, const std::string& message)
232 {
233     TAG_LOGI(AAFwkTag::FORM_EXT, "formId: %{public}" PRId64, formId);
234     FormExtension::OnEvent(formId, message);
235 
236     HandleScope handleScope(jsRuntime_);
237     napi_env env = jsRuntime_.GetNapiEnv();
238     // wrap formId
239     napi_value napiFormId = nullptr;
240     napi_create_string_utf8(env, std::to_string(formId).c_str(),
241         NAPI_AUTO_LENGTH, &napiFormId);
242     // wrap message
243     napi_value napiMessage = nullptr;
244     napi_create_string_utf8(env, message.c_str(), NAPI_AUTO_LENGTH, &napiMessage);
245     napi_value argv[] = {napiFormId, napiMessage};
246     CallObjectMethod("onFormEvent", "onEvent", argv, ON_EVENT_PARAMS_SIZE);
247 }
248 
OnUpdate(const int64_t formId,const AAFwk::WantParams & wantParams)249 void JsFormExtension::OnUpdate(const int64_t formId, const AAFwk::WantParams &wantParams)
250 {
251     TAG_LOGI(AAFwkTag::FORM_EXT, "formId: %{public}" PRId64, formId);
252     FormExtension::OnUpdate(formId, wantParams);
253 
254     HandleScope handleScope(jsRuntime_);
255     napi_env env = jsRuntime_.GetNapiEnv();
256     // wrap formId
257     napi_value napiFormId = nullptr;
258     napi_create_string_utf8(env, std::to_string(formId).c_str(),
259         NAPI_AUTO_LENGTH, &napiFormId);
260     // wrap wantParams
261     napi_value nativeObj = WrapWantParams(env, wantParams);
262     napi_value argv[] = {napiFormId, nativeObj};
263     CallObjectMethod("onUpdateForm", "onUpdate", argv, ARGC_TWO);
264 }
265 
OnCastToNormal(const int64_t formId)266 void JsFormExtension::OnCastToNormal(const int64_t formId)
267 {
268     TAG_LOGI(AAFwkTag::FORM_EXT, "formId: %{public}" PRId64, formId);
269     FormExtension::OnCastToNormal(formId);
270 
271     HandleScope handleScope(jsRuntime_);
272     napi_env env = jsRuntime_.GetNapiEnv();
273     // wrap formId
274     napi_value napiFormId = nullptr;
275     napi_create_string_utf8(env, std::to_string(formId).c_str(), NAPI_AUTO_LENGTH,
276         &napiFormId);
277     napi_value argv[] = {napiFormId};
278     CallObjectMethod("onCastToNormalForm", "onCastToNormal", argv, 1);
279 }
280 
OnVisibilityChange(const std::map<int64_t,int32_t> & formEventsMap)281 void JsFormExtension::OnVisibilityChange(const std::map<int64_t, int32_t>& formEventsMap)
282 {
283     TAG_LOGI(AAFwkTag::FORM_EXT, "call");
284     FormExtension::OnVisibilityChange(formEventsMap);
285     HandleScope handleScope(jsRuntime_);
286     napi_env env = jsRuntime_.GetNapiEnv();
287     napi_value nativeObj = nullptr;
288     napi_create_object(env, &nativeObj);
289     for (auto item = formEventsMap.begin(); item != formEventsMap.end(); item++) {
290         napi_set_named_property(env, nativeObj, std::to_string(item->first).c_str(), CreateJsValue(env, item->second));
291     }
292     napi_value argv[] = {nativeObj};
293     CallObjectMethod("onChangeFormVisibility", "onVisibilityChange", argv, 1);
294 }
295 
OnConnect(const OHOS::AAFwk::Want & want)296 sptr<IRemoteObject> JsFormExtension::OnConnect(const OHOS::AAFwk::Want& want)
297 {
298     TAG_LOGD(AAFwkTag::FORM_EXT, "call");
299     Extension::OnConnect(want);
300     if (providerRemoteObject_ == nullptr) {
301         TAG_LOGD(AAFwkTag::FORM_EXT, "null providerRemoteObject");
302         sptr<FormExtensionProviderClient> providerClient = new (std::nothrow) FormExtensionProviderClient();
303         std::shared_ptr<JsFormExtension> formExtension = std::static_pointer_cast<JsFormExtension>(shared_from_this());
304         providerClient->SetOwner(formExtension);
305         providerRemoteObject_ = providerClient->AsObject();
306     }
307     return providerRemoteObject_;
308 }
309 
CallObjectMethod(const char * name,const char * bakName,napi_value const * argv,size_t argc)310 napi_value JsFormExtension::CallObjectMethod(const char* name, const char *bakName, napi_value const* argv,
311     size_t argc)
312 {
313     TAG_LOGD(AAFwkTag::FORM_EXT, "CallObjectMethod(%{public}s)", name);
314     if (!jsObj_) {
315         TAG_LOGW(AAFwkTag::FORM_EXT, "jsObj null");
316         return nullptr;
317     }
318 
319     HandleEscape handleEscape(jsRuntime_);
320     napi_env env = jsRuntime_.GetNapiEnv();
321 
322     napi_value obj = jsObj_->GetNapiValue();
323     if (!CheckTypeForNapiValue(env, obj, napi_object)) {
324         TAG_LOGE(AAFwkTag::FORM_EXT, "get FormExtension failed");
325         return nullptr;
326     }
327 
328     napi_value method = nullptr;
329     napi_get_named_property(env, obj, name, &method);
330     if (!CheckTypeForNapiValue(env, method, napi_function)) {
331         TAG_LOGE(AAFwkTag::FORM_EXT, "get '%{public}s' failed", name);
332         if (bakName == nullptr) {
333             return nullptr;
334         }
335         method = nullptr;
336         napi_get_named_property(env, obj, bakName, &method);
337         if (!CheckTypeForNapiValue(env, method, napi_function)) {
338             TAG_LOGE(AAFwkTag::FORM_EXT, "Failed to get '%{public}s' from FormExtension object", bakName);
339             return nullptr;
340         }
341     }
342     TAG_LOGD(AAFwkTag::FORM_EXT, "CallFunction(%{public}s), ok", name);
343     napi_value result = nullptr;
344     napi_call_function(env, obj, method, argc, argv, &result);
345     return handleEscape.Escape(result);
346 }
347 
GetSrcPath(std::string & srcPath)348 void JsFormExtension::GetSrcPath(std::string &srcPath)
349 {
350     if (!Extension::abilityInfo_->isModuleJson) {
351         /* temporary compatibility api8 + config.json */
352         srcPath.append(Extension::abilityInfo_->package);
353         srcPath.append("/assets/js/");
354         if (!Extension::abilityInfo_->srcPath.empty()) {
355             srcPath.append(Extension::abilityInfo_->srcPath);
356         }
357         srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
358         return;
359     }
360 
361     if (!Extension::abilityInfo_->srcEntrance.empty()) {
362         srcPath.append(Extension::abilityInfo_->moduleName + "/");
363         srcPath.append(Extension::abilityInfo_->srcEntrance);
364         srcPath.erase(srcPath.rfind('.'));
365         srcPath.append(".abc");
366     }
367 }
368 
OnConfigurationUpdated(const AppExecFwk::Configuration & configuration)369 void JsFormExtension::OnConfigurationUpdated(const AppExecFwk::Configuration& configuration)
370 {
371     FormExtension::OnConfigurationUpdated(configuration);
372     TAG_LOGI(AAFwkTag::FORM_EXT, "call");
373 
374     HandleScope handleScope(jsRuntime_);
375     napi_env env = jsRuntime_.GetNapiEnv();
376 
377     // Notify extension context
378     auto fullConfig = GetContext()->GetConfiguration();
379     if (!fullConfig) {
380         TAG_LOGE(AAFwkTag::FORM_EXT, "configuration null");
381         return;
382     }
383     JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, fullConfig);
384 
385     napi_value napiConfiguration = OHOS::AppExecFwk::WrapConfiguration(env, *fullConfig);
386     CallObjectMethod("onConfigurationUpdate", "onConfigurationUpdated", &napiConfiguration, 1);
387 }
388 
OnAcquireFormState(const Want & want)389 FormState JsFormExtension::OnAcquireFormState(const Want &want)
390 {
391     TAG_LOGI(AAFwkTag::FORM_EXT, "call");
392     auto state = static_cast<int32_t>(FormState::DEFAULT);
393     HandleScope handleScope(jsRuntime_);
394     napi_env env = jsRuntime_.GetNapiEnv();
395     napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
396 
397     napi_value argv[] = { napiWant };
398     napi_value nativeResult = CallObjectMethod("onAcquireFormState", nullptr, argv, 1);
399     if (nativeResult == nullptr) {
400         TAG_LOGI(AAFwkTag::FORM_EXT, "onAcquireFormState not found");
401         return FormState::DEFAULT;
402     }
403 
404     if (!ConvertFromJsValue(env, nativeResult, state)) {
405         TAG_LOGE(AAFwkTag::FORM_EXT, "convert failed");
406         return FormState::UNKNOWN;
407     }
408 
409     TAG_LOGI(AAFwkTag::FORM_EXT, "state: %{public}d", state);
410     if (state <= static_cast<int32_t>(AppExecFwk::FormState::UNKNOWN) ||
411         state > static_cast<int32_t>(AppExecFwk::FormState::READY)) {
412         return AppExecFwk::FormState::UNKNOWN;
413     } else {
414         return static_cast<AppExecFwk::FormState>(state);
415     }
416 }
417 
OnShare(int64_t formId,AAFwk::WantParams & wantParams)418 bool JsFormExtension::OnShare(int64_t formId, AAFwk::WantParams &wantParams)
419 {
420     TAG_LOGD(AAFwkTag::FORM_EXT, "formId: %{public}" PRId64, formId);
421     HandleScope handleScope(jsRuntime_);
422     napi_env env = jsRuntime_.GetNapiEnv();
423     if (env == nullptr) {
424         TAG_LOGE(AAFwkTag::FORM_EXT, "env null");
425         return false;
426     }
427 
428     auto formIdStr = std::to_string(formId);
429     napi_value argv[] = { CreateJsValue(env, formIdStr) };
430     napi_value nativeResult = CallObjectMethod("onShareForm", "onShare", argv, 1);
431     if (nativeResult == nullptr) {
432         TAG_LOGE(AAFwkTag::FORM_EXT, "nativeResult null");
433         return false;
434     }
435 
436     if (!CheckTypeForNapiValue(env, nativeResult, napi_object)) {
437         TAG_LOGE(AAFwkTag::FORM_EXT, "nativeResult not object");
438         return false;
439     }
440 
441     if (!OHOS::AppExecFwk::UnwrapWantParams(env, nativeResult, wantParams)) {
442         TAG_LOGE(AAFwkTag::FORM_EXT, "unwrap want failed");
443         return false;
444     }
445 
446     return true;
447 }
448 
OnAcquireData(int64_t formId,AAFwk::WantParams & wantParams)449 bool JsFormExtension::OnAcquireData(int64_t formId, AAFwk::WantParams &wantParams)
450 {
451     TAG_LOGD(AAFwkTag::FORM_EXT, "formId: %{public}" PRId64, formId);
452     HandleScope handleScope(jsRuntime_);
453     napi_env env = jsRuntime_.GetNapiEnv();
454     if (env == nullptr) {
455         TAG_LOGE(AAFwkTag::FORM_EXT, "env null");
456         return false;
457     }
458 
459     auto formIdStr = std::to_string(formId);
460     napi_value argv[] = { CreateJsValue(env, formIdStr) };
461     napi_value nativeResult = CallObjectMethod("onAcquireFormData", "OnAcquireData", argv, 1);
462     if (nativeResult == nullptr) {
463         TAG_LOGE(AAFwkTag::FORM_EXT, "nativeResult null");
464         return false;
465     }
466 
467     if (!CheckTypeForNapiValue(env, nativeResult, napi_object)) {
468         TAG_LOGE(AAFwkTag::FORM_EXT, "nativeResult not object");
469         return false;
470     }
471 
472     if (!OHOS::AppExecFwk::UnwrapWantParams(env, nativeResult, wantParams)) {
473         TAG_LOGE(AAFwkTag::FORM_EXT, "argc failed");
474         return false;
475     }
476     return true;
477 }
478 
ConvertFromDataProxies(napi_env env,napi_value jsValue,std::vector<FormDataProxy> & formDataProxies)479 bool JsFormExtension::ConvertFromDataProxies(napi_env env, napi_value jsValue,
480     std::vector<FormDataProxy> &formDataProxies)
481 {
482     if (jsValue == nullptr) {
483         TAG_LOGE(AAFwkTag::FORM_EXT, "jsValue null");
484         return false;
485     }
486 
487     uint32_t len = 0;
488     NAPI_CALL_NO_THROW(napi_get_array_length(env, jsValue, &len), false);
489     for (uint32_t i = 0; i < len; i++) {
490         FormDataProxy formDataProxy("", "");
491         napi_value element = nullptr;
492         napi_get_element(env, jsValue, i, &element);
493         if (!ConvertFormDataProxy(env, element, formDataProxy)) {
494             TAG_LOGE(AAFwkTag::FORM_EXT, "GetElement from array [%{public}u] error", i);
495             continue;
496         }
497         formDataProxies.push_back(formDataProxy);
498     }
499     return true;
500 }
501 
ConvertFormDataProxy(napi_env env,napi_value jsValue,FormDataProxy & formDataProxy)502 bool JsFormExtension::ConvertFormDataProxy(napi_env env, napi_value jsValue, FormDataProxy &formDataProxy)
503 {
504     if (!CheckTypeForNapiValue(env, jsValue, napi_object)) {
505         TAG_LOGE(AAFwkTag::FORM_EXT, "jsValue null");
506         return false;
507     }
508 
509     napi_value key = nullptr;
510     napi_get_named_property(env, jsValue, "key", &key);
511     if (!ConvertFromJsValue(env, key, formDataProxy.key)) {
512         TAG_LOGE(AAFwkTag::FORM_EXT, "Parse key failed");
513         return false;
514     }
515     napi_value subscribeId = nullptr;
516     napi_get_named_property(env, jsValue, "subscriberId", &subscribeId);
517     if (subscribeId != nullptr && !ConvertFromJsValue(env, subscribeId, formDataProxy.subscribeId)) {
518         TAG_LOGW(AAFwkTag::FORM_EXT, "Parse subscriberId failed");
519         formDataProxy.subscribeId = "";
520     }
521     TAG_LOGI(AAFwkTag::FORM_EXT, "key is %{public}s, subscriberId is %{public}s", formDataProxy.key.c_str(),
522         formDataProxy.subscribeId.c_str());
523     return true;
524 }
525 } // namespace AbilityRuntime
526 } // namespace OHOS
527