1 /*
2 * Copyright (c) 2023-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 "js_auto_fill_extension_util.h"
17
18 #include "hilog_tag_wrapper.h"
19 #include "napi_common_util.h"
20 #include "napi_common_want.h"
21
22 namespace OHOS {
23 namespace AbilityRuntime {
24 namespace {
25 constexpr const char *VIEW_DATA_BUNDLE_NAME = "bundleName";
26 constexpr const char *VIEW_DATA_MODULE_NAME = "moduleName";
27 constexpr const char *VIEW_DATA_ABILITY_NAME = "abilityName";
28 constexpr const char *VIEW_DATA_PAGEURL = "pageUrl";
29 constexpr const char *VIEW_DATA_USER_SELECTED = "isUserSelected";
30 constexpr const char *VIEW_DATA_OTHER_ACCOUNT = "isOtherAccount";
31 constexpr const char *VIEW_DATA_PAGE_NODE_INFOS = "pageNodeInfos";
32 constexpr const char *VIEW_DATA_VIEW_DATA = "viewData";
33 constexpr const char *VIEW_DATA_TYPE = "type";
34 constexpr const char *VIEW_DATA_PAGE_RECT = "pageRect";
35 constexpr const char *CUSTOM_DATA_CUSTOM_DATA = "customData";
36 constexpr const char *CUSTOM_DATA_DATA = "data";
37 constexpr const char *PAGE_INFO_ID = "id";
38 constexpr const char *PAGE_INFO_DEPTH = "depth";
39 constexpr const char *PAGE_INFO_AUTOFILLTYPE = "autoFillType";
40 constexpr const char *PAGE_INFO_TAG = "tag";
41 constexpr const char *PAGE_INFO_VALUE = "value";
42 constexpr const char *PAGE_INFO_PLACEHOLDER = "placeholder";
43 constexpr const char *PAGE_INFO_META_DATA = "metadata";
44 constexpr const char *PAGE_INFO_PASSWORDRULES = "passwordRules";
45 constexpr const char *PAGE_INFO_ENABLEAUTOFILL = "enableAutoFill";
46 constexpr const char *PAGE_INFO_IS_FOCUS = "isFocus";
47 constexpr const char *PAGE_INFO_PAGE_NODE_RECT = "rect";
48 constexpr const char *WANT_PARAMS_VIEW_DATA = "ohos.ability.params.viewData";
49 constexpr const char *WANT_PARAMS_CUSTOM_DATA = "ohos.ability.params.customData";
50 constexpr const char *WANT_PARAMS_AUTO_FILL_TYPE_KEY = "ability.want.params.AutoFillType";
51 constexpr const char *WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY = "ohos.ability.params.popupWindow";
52 constexpr const char *WANT_PARAMS_IS_POPUP = "isPopup";
53 constexpr const char *RECT_POSITION_LEFT = "left";
54 constexpr const char *RECT_POSITION_TOP = "top";
55 constexpr const char *RECT_WIDTH = "width";
56 constexpr const char *RECT_HEIGHT = "height";
57 constexpr uint32_t PAGE_NODE_COUNT_MAX = 100;
58 } // namespace
59
WrapViewData(const napi_env env,const AbilityBase::ViewData & viewData)60 napi_value JsAutoFillExtensionUtil::WrapViewData(const napi_env env, const AbilityBase::ViewData &viewData)
61 {
62 TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called");
63 napi_value jsObject = nullptr;
64 NAPI_CALL(env, napi_create_object(env, &jsObject));
65 napi_value jsValue = nullptr;
66 jsValue = WrapStringToJS(env, viewData.bundleName);
67 SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_BUNDLE_NAME, jsValue);
68
69 jsValue = WrapStringToJS(env, viewData.abilityName);
70 SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_ABILITY_NAME, jsValue);
71
72 jsValue = WrapStringToJS(env, viewData.moduleName);
73 SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_MODULE_NAME, jsValue);
74
75 jsValue = WrapStringToJS(env, viewData.pageUrl);
76 SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_PAGEURL, jsValue);
77
78 jsValue = WrapBoolToJS(env, viewData.isUserSelected);
79 SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_USER_SELECTED, jsValue);
80
81 jsValue = WrapBoolToJS(env, viewData.isOtherAccount);
82 SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_OTHER_ACCOUNT, jsValue);
83
84 napi_value jsArray = nullptr;
85 NAPI_CALL(env, napi_create_array(env, &jsArray));
86 napi_value jsSubValue = nullptr;
87 uint32_t index = 0;
88 for (auto element : viewData.nodes) {
89 jsSubValue = WrapPageNodeInfo(env, element);
90 if (jsSubValue != nullptr && napi_set_element(env, jsArray, index, jsSubValue) == napi_ok) {
91 index++;
92 } else {
93 TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "Set element fail");
94 }
95 }
96
97 jsValue = WrapRectData(env, viewData.pageRect);
98 SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_PAGE_RECT, jsValue);
99
100 SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_PAGE_NODE_INFOS, jsArray);
101 return jsObject;
102 }
103
WrapCustomData(const napi_env env,const AAFwk::WantParams & param)104 napi_value JsAutoFillExtensionUtil::WrapCustomData(const napi_env env, const AAFwk::WantParams ¶m)
105 {
106 TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called");
107 napi_value jsObject = nullptr;
108 NAPI_CALL(env, napi_create_object(env, &jsObject));
109 napi_value jsValue = nullptr;
110 jsValue = WrapWantParams(env, param);
111 SetPropertyValueByPropertyName(env, jsObject, CUSTOM_DATA_DATA, jsValue);
112 return jsObject;
113 }
114
WrapPageNodeInfo(const napi_env env,const AbilityBase::PageNodeInfo & pageNodeInfo)115 napi_value JsAutoFillExtensionUtil::WrapPageNodeInfo(const napi_env env, const AbilityBase::PageNodeInfo &pageNodeInfo)
116 {
117 TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called");
118 napi_value jsObject = nullptr;
119 NAPI_CALL(env, napi_create_object(env, &jsObject));
120 napi_value jsValue = nullptr;
121 jsValue = AppExecFwk::WrapInt32ToJS(env, pageNodeInfo.id);
122 SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_ID, jsValue);
123
124 jsValue = AppExecFwk::WrapInt32ToJS(env, pageNodeInfo.depth);
125 SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_DEPTH, jsValue);
126
127 jsValue = AppExecFwk::WrapInt32ToJS(env, static_cast<int32_t>(pageNodeInfo.autoFillType));
128 SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_AUTOFILLTYPE, jsValue);
129
130 jsValue = WrapStringToJS(env, pageNodeInfo.tag);
131 SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_TAG, jsValue);
132
133 jsValue = WrapStringToJS(env, pageNodeInfo.value);
134 SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_VALUE, jsValue);
135
136 jsValue = WrapStringToJS(env, pageNodeInfo.passwordRules);
137 SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_PASSWORDRULES, jsValue);
138
139 jsValue = WrapStringToJS(env, pageNodeInfo.placeholder);
140 SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_PLACEHOLDER, jsValue);
141
142 jsValue = WrapStringToJS(env, pageNodeInfo.metadata);
143 SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_META_DATA, jsValue);
144
145 jsValue = WrapBoolToJS(env, pageNodeInfo.enableAutoFill);
146 SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_ENABLEAUTOFILL, jsValue);
147
148 jsValue = WrapRectData(env, pageNodeInfo.rect);
149 SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_PAGE_NODE_RECT, jsValue);
150
151 jsValue = WrapBoolToJS(env, pageNodeInfo.isFocus);
152 SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_IS_FOCUS, jsValue);
153
154 return jsObject;
155 }
156
WrapRectData(const napi_env env,const AbilityBase::Rect & rect)157 napi_value JsAutoFillExtensionUtil::WrapRectData(const napi_env env, const AbilityBase::Rect &rect)
158 {
159 TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called");
160 napi_value jsObject = nullptr;
161 NAPI_CALL(env, napi_create_object(env, &jsObject));
162 napi_value jsValue = nullptr;
163 jsValue = AppExecFwk::WrapDoubleToJS(env, rect.left);
164 SetPropertyValueByPropertyName(env, jsObject, RECT_POSITION_LEFT, jsValue);
165
166 jsValue = AppExecFwk::WrapDoubleToJS(env, rect.top);
167 SetPropertyValueByPropertyName(env, jsObject, RECT_POSITION_TOP, jsValue);
168
169 jsValue = AppExecFwk::WrapDoubleToJS(env, rect.width);
170 SetPropertyValueByPropertyName(env, jsObject, RECT_WIDTH, jsValue);
171
172 jsValue = AppExecFwk::WrapDoubleToJS(env, rect.height);
173 SetPropertyValueByPropertyName(env, jsObject, RECT_HEIGHT, jsValue);
174
175 return jsObject;
176 }
177
UnwrapViewData(const napi_env env,const napi_value value,AbilityBase::ViewData & viewData)178 void JsAutoFillExtensionUtil::UnwrapViewData(
179 const napi_env env, const napi_value value, AbilityBase::ViewData &viewData)
180 {
181 TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called");
182 napi_value jsViewData = GetPropertyValueByPropertyName(env, value, VIEW_DATA_VIEW_DATA, napi_object);
183 if (jsViewData == nullptr) {
184 TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "Get ViewData from JS failed");
185 return;
186 }
187
188 napi_value jsValue = nullptr;
189 jsValue = GetPropertyValueByPropertyName(env, jsViewData, VIEW_DATA_BUNDLE_NAME, napi_string);
190 viewData.bundleName = UnwrapStringFromJS(env, jsValue, "");
191 jsValue = GetPropertyValueByPropertyName(env, jsViewData, VIEW_DATA_MODULE_NAME, napi_string);
192 viewData.moduleName = UnwrapStringFromJS(env, jsValue, "");
193 jsValue = GetPropertyValueByPropertyName(env, jsViewData, VIEW_DATA_ABILITY_NAME, napi_string);
194 viewData.abilityName = UnwrapStringFromJS(env, jsValue, "");
195 jsValue = GetPropertyValueByPropertyName(env, jsViewData, VIEW_DATA_PAGEURL, napi_string);
196 viewData.pageUrl = UnwrapStringFromJS(env, jsValue, "");
197 UnwrapBooleanByPropertyName(env, jsViewData, VIEW_DATA_USER_SELECTED, viewData.isUserSelected);
198 UnwrapBooleanByPropertyName(env, jsViewData, VIEW_DATA_OTHER_ACCOUNT, viewData.isOtherAccount);
199 jsValue = GetPropertyValueByPropertyName(env, jsViewData, VIEW_DATA_PAGE_NODE_INFOS, napi_object);
200 if (jsValue != nullptr) {
201 uint32_t jsProCount = 0;
202 if (!IsArrayForNapiValue(env, jsValue, jsProCount)) {
203 TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "Get PAGE_NODE_INFOS from JS failed");
204 return;
205 }
206
207 for (uint32_t index = 0; index < jsProCount && index < PAGE_NODE_COUNT_MAX; index++) {
208 napi_value jsNode = nullptr;
209 napi_get_element(env, jsValue, index, &jsNode);
210 AbilityBase::PageNodeInfo node;
211 UnwrapPageNodeInfo(env, jsNode, node);
212 viewData.nodes.emplace_back(node);
213 }
214 }
215 jsValue = GetPropertyValueByPropertyName(env, jsViewData, VIEW_DATA_PAGE_RECT, napi_object);
216 UnwrapRectData(env, jsValue, viewData.pageRect);
217 }
218
UnwrapPageNodeInfo(const napi_env env,const napi_value jsNode,AbilityBase::PageNodeInfo & node)219 void JsAutoFillExtensionUtil::UnwrapPageNodeInfo(
220 const napi_env env, const napi_value jsNode, AbilityBase::PageNodeInfo &node)
221 {
222 TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called");
223 UnwrapInt32ByPropertyName(env, jsNode, PAGE_INFO_ID, node.id);
224 UnwrapInt32ByPropertyName(env, jsNode, PAGE_INFO_DEPTH, node.depth);
225 int32_t type;
226 UnwrapInt32ByPropertyName(env, jsNode, PAGE_INFO_AUTOFILLTYPE, type);
227 node.autoFillType = static_cast<AbilityBase::AutoFillType>(type);
228 UnwrapStringByPropertyName(env, jsNode, PAGE_INFO_TAG, node.tag);
229 UnwrapStringByPropertyName(env, jsNode, PAGE_INFO_VALUE, node.value);
230 UnwrapStringByPropertyName(env, jsNode, PAGE_INFO_PASSWORDRULES, node.passwordRules);
231 UnwrapStringByPropertyName(env, jsNode, PAGE_INFO_PLACEHOLDER, node.placeholder);
232 UnwrapStringByPropertyName(env, jsNode, PAGE_INFO_META_DATA, node.metadata);
233 UnwrapBooleanByPropertyName(env, jsNode, PAGE_INFO_ENABLEAUTOFILL, node.enableAutoFill);
234 auto jsValue = GetPropertyValueByPropertyName(env, jsNode, PAGE_INFO_PAGE_NODE_RECT, napi_object);
235 UnwrapRectData(env, jsValue, node.rect);
236 UnwrapBooleanByPropertyName(env, jsNode, PAGE_INFO_IS_FOCUS, node.isFocus);
237 }
238
UnwrapRectData(const napi_env env,const napi_value value,AbilityBase::Rect & rect)239 void JsAutoFillExtensionUtil::UnwrapRectData(
240 const napi_env env, const napi_value value, AbilityBase::Rect &rect)
241 {
242 TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called");
243 int32_t position;
244 UnwrapInt32ByPropertyName(env, value, RECT_POSITION_LEFT, position);
245 rect.left = position;
246
247 UnwrapInt32ByPropertyName(env, value, RECT_POSITION_TOP, position);
248 rect.top = position;
249
250 UnwrapInt32ByPropertyName(env, value, RECT_WIDTH, position);
251 rect.width = position;
252
253 UnwrapInt32ByPropertyName(env, value, RECT_HEIGHT, position);
254 rect.height = position;
255 }
256
WrapFillRequest(const AAFwk::Want & want,const napi_env env)257 napi_value JsAutoFillExtensionUtil::WrapFillRequest(const AAFwk::Want &want, const napi_env env)
258 {
259 TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called");
260 napi_value jsObject = nullptr;
261 NAPI_CALL(env, napi_create_object(env, &jsObject));
262 if (jsObject == nullptr) {
263 TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "create jsObject failed");
264 return nullptr;
265 }
266
267 if (want.HasParameter(WANT_PARAMS_AUTO_FILL_TYPE_KEY)) {
268 auto type = want.GetIntParam(WANT_PARAMS_AUTO_FILL_TYPE_KEY, -1);
269 TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "Auto fill request type: %{public}d", type);
270
271 napi_value jsValue = AppExecFwk::WrapInt32ToJS(env, type);
272 SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_TYPE, jsValue);
273 }
274
275 if (want.HasParameter(WANT_PARAMS_VIEW_DATA)) {
276 std::string viewDataString = want.GetStringParam(WANT_PARAMS_VIEW_DATA);
277 if (viewDataString.empty()) {
278 TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "empty view data");
279 return jsObject;
280 }
281
282 AbilityBase::ViewData viewData;
283 viewData.FromJsonString(viewDataString);
284 napi_value viewDataValue = WrapViewData(env, viewData);
285 SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_VIEW_DATA, viewDataValue);
286 }
287
288 if (want.HasParameter(WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY)) {
289 auto isPopup = want.GetBoolParam(WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY, false);
290
291 napi_value jsValue = AppExecFwk::WrapBoolToJS(env, isPopup);
292 SetPropertyValueByPropertyName(env, jsObject, WANT_PARAMS_IS_POPUP, jsValue);
293 }
294
295 if (want.HasParameter(WANT_PARAMS_CUSTOM_DATA)) {
296 std::string customDataString = want.GetStringParam(WANT_PARAMS_CUSTOM_DATA);
297 if (customDataString.empty()) {
298 TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "empty custom data");
299 return jsObject;
300 }
301 if (!AAFwk::WantParamWrapper::ValidateStr(customDataString)) {
302 TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "invalid Custom data string");
303 return jsObject;
304 }
305 AAFwk::WantParams param = AAFwk::WantParamWrapper::ParseWantParams(customDataString);
306 napi_value customValue = nullptr;
307 customValue = WrapCustomData(env, param);
308 SetPropertyValueByPropertyName(env, jsObject, CUSTOM_DATA_CUSTOM_DATA, customValue);
309 }
310 return jsObject;
311 }
312
WrapUpdateRequest(const AAFwk::WantParams & wantParams,const napi_env env)313 napi_value JsAutoFillExtensionUtil::WrapUpdateRequest(const AAFwk::WantParams &wantParams, const napi_env env)
314 {
315 TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called");
316 napi_value jsObject = nullptr;
317 NAPI_CALL(env, napi_create_object(env, &jsObject));
318 if (jsObject == nullptr) {
319 TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "Failed to create Object");
320 return nullptr;
321 }
322
323 std::string viewDataString = wantParams.GetStringParam(WANT_PARAMS_VIEW_DATA);
324 if (viewDataString.empty()) {
325 TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "empty view data");
326 return jsObject;
327 }
328
329 AbilityBase::ViewData viewData;
330 viewData.FromJsonString(viewDataString);
331 napi_value viewDataValue = WrapViewData(env, viewData);
332 SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_VIEW_DATA, viewDataValue);
333 return jsObject;
334 }
335
UnwrapFillResponse(const napi_env env,const napi_value value,FillResponse & response)336 void JsAutoFillExtensionUtil::UnwrapFillResponse(const napi_env env, const napi_value value, FillResponse &response)
337 {
338 TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called");
339 UnwrapViewData(env, value, response.viewData);
340 }
341
UnwrapPopupSize(const napi_env env,const napi_value value,PopupSize & popupSize)342 void JsAutoFillExtensionUtil::UnwrapPopupSize(const napi_env env, const napi_value value, PopupSize &popupSize)
343 {
344 UnwrapInt32ByPropertyName(env, value, RECT_WIDTH, popupSize.width);
345 UnwrapInt32ByPropertyName(env, value, RECT_HEIGHT, popupSize.height);
346 }
347 } // namespace AbilityRuntime
348 } // namespace OHOS