From aea79204bb18458dcb260e175658760040a3b37c Mon Sep 17 00:00:00 2001 From: zhangzezhong Date: Tue, 3 Jun 2025 13:45:29 +0800 Subject: [PATCH] add AutoFillExtensionContext and AutoFillRequest Signed-off-by: zhangzezhong --- frameworks/ets/ets/BUILD.gn | 136 +++++++ .../application/AutoFillExtensionContext.ets | 39 ++ .../ets/application/AutoFillPopupConfig.ets | 47 +++ .../ets/ets/application/AutoFillRect.ets | 28 ++ .../ets/ets/application/AutoFillRequest.ets | 75 ++++ .../ets/ets/application/AutoFillType.ets | 51 +++ frameworks/ets/ets/application/CustomData.ets | 22 + .../ets/ets/application/PageNodeInfo.ets | 45 ++ frameworks/ets/ets/application/ViewData.ets | 39 ++ frameworks/native/ability/native/BUILD.gn | 5 + .../ets_auto_fill_extension_context.cpp | 176 ++++++++ .../ets_auto_fill_extension_util.cpp | 234 +++++++++++ .../ets_fill_request_callback.cpp | 385 ++++++++++++++++++ .../ets_save_request_callback.cpp | 252 ++++++++++++ .../ets_auto_fill_extension_context.h | 43 ++ .../ets_auto_fill_extension_util.h | 72 ++++ .../ets_fill_request_callback.h | 57 +++ .../ets_save_request_callback.h | 52 +++ 18 files changed, 1758 insertions(+) create mode 100644 frameworks/ets/ets/application/AutoFillExtensionContext.ets create mode 100644 frameworks/ets/ets/application/AutoFillPopupConfig.ets create mode 100644 frameworks/ets/ets/application/AutoFillRect.ets create mode 100644 frameworks/ets/ets/application/AutoFillRequest.ets create mode 100644 frameworks/ets/ets/application/AutoFillType.ets create mode 100644 frameworks/ets/ets/application/CustomData.ets create mode 100644 frameworks/ets/ets/application/PageNodeInfo.ets create mode 100644 frameworks/ets/ets/application/ViewData.ets create mode 100644 frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_context.cpp create mode 100644 frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.cpp create mode 100644 frameworks/native/ability/native/auto_fill_extension_ability/ets_fill_request_callback.cpp create mode 100644 frameworks/native/ability/native/auto_fill_extension_ability/ets_save_request_callback.cpp create mode 100644 interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_context.h create mode 100644 interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.h create mode 100644 interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_fill_request_callback.h create mode 100644 interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_save_request_callback.h diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn index ae9a2fc41a8..0c016655912 100644 --- a/frameworks/ets/ets/BUILD.gn +++ b/frameworks/ets/ets/BUILD.gn @@ -128,6 +128,22 @@ ohos_prebuilt_etc("ability_runtime_context_abc_etc") { deps = [ ":ability_runtime_context_abc" ] } +generate_static_abc("ability_runtime_custom_data_abc") { + base_url = "./" + files = [ "./application/CustomData.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_custom_data_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_custom_data_abc_etc") { + source = "$target_out_dir/ability_runtime_custom_data_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_custom_data_abc" ] +} + generate_static_abc("ability_runtime_base_context_abc") { base_url = "./" files = [ "./application/BaseContext.ets" ] @@ -498,6 +514,86 @@ ohos_prebuilt_etc("ability_runtime_app_state_data_abc_etc") { deps = [ ":ability_runtime_app_state_data_abc" ] } +generate_static_abc("ability_runtime_auto_fill_extension_context_abc") { + base_url = "./" + files = [ "./application/AutoFillExtensionContext.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_auto_fill_extension_context_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_auto_fill_extension_context_abc_etc") { + source = "$target_out_dir/ability_runtime_auto_fill_extension_context_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_auto_fill_extension_context_abc" ] +} + +generate_static_abc("ability_runtime_auto_fill_popup_config_abc") { + base_url = "./" + files = [ "./application/AutoFillPopupConfig.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_auto_fill_popup_config_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_auto_fill_popup_config_abc_etc") { + source = "$target_out_dir/ability_runtime_auto_fill_popup_config_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_auto_fill_popup_config_abc" ] +} + +generate_static_abc("ability_runtime_auto_fill_rect_abc") { + base_url = "./" + files = [ "./application/AutoFillRect.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_auto_fill_rect_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_auto_fill_rect_abc_etc") { + source = "$target_out_dir/ability_runtime_auto_fill_rect_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_auto_fill_rect_abc" ] +} + +generate_static_abc("ability_runtime_auto_fill_request_abc") { + base_url = "./" + files = [ "./application/AutoFillRequest.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_auto_fill_request_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_auto_fill_request_abc_etc") { + source = "$target_out_dir/ability_runtime_auto_fill_request_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_auto_fill_request_abc" ] +} + +generate_static_abc("ability_runtime_auto_fill_type_abc") { + base_url = "./" + files = [ "./application/AutoFillType.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_auto_fill_type_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_auto_fill_type_abc_etc") { + source = "$target_out_dir/ability_runtime_auto_fill_type_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_auto_fill_type_abc" ] +} + generate_static_abc("ability_runtime_process_data_abc") { base_url = "./" files = [ "./application/ProcessData.ets" ] @@ -564,6 +660,38 @@ ohos_prebuilt_etc("ability_runtime_multi_app_mode_abc_etc") { deps = [ ":ability_runtime_multi_app_mode_abc" ] } +generate_static_abc("ability_runtime_page_node_info_abc") { + base_url = "./" + files = [ "./application/PageNodeInfo.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_page_node_info_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_page_node_info_abc_etc") { + source = "$target_out_dir/ability_runtime_page_node_info_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_page_node_info_abc" ] +} + +generate_static_abc("ability_runtime_view_data_abc") { + base_url = "./" + files = [ "./application/ViewData.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_view_data_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_view_data_abc_etc") { + source = "$target_out_dir/ability_runtime_view_data_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_view_data_abc" ] +} + generate_static_abc("ability_runtime_app_manager_abc") { base_url = "./" files = [ "./@ohos.app.ability.appManager.ets" ] @@ -821,11 +949,17 @@ group("ets_packages") { ":ability_runtime_ability_utils_abc_etc", ":ability_runtime_app_manager_abc_etc", ":ability_runtime_app_state_data_abc_etc", + ":ability_runtime_auto_fill_extension_context_abc_etc", + ":ability_runtime_auto_fill_popup_config_abc_etc", + ":ability_runtime_auto_fill_rect_abc_etc", + ":ability_runtime_auto_fill_request_abc_etc", + ":ability_runtime_auto_fill_type_abc_etc", ":ability_runtime_application_context_abc_etc", ":ability_runtime_base_context_abc_etc", ":ability_runtime_configuration_abc_etc", ":ability_runtime_configuration_constant_abc_etc", ":ability_runtime_context_abc_etc", + ":ability_runtime_custom_data_abc_etc", ":ability_runtime_environment_callback_abc_etc", ":ability_runtime_event_hub_abc_etc", ":ability_runtime_extension_context_abc_etc", @@ -834,6 +968,8 @@ group("ets_packages") { ":ability_runtime_insight_intent_driver_abc_etc", ":ability_runtime_insight_intent_executor_abc_etc", ":ability_runtime_multi_app_mode_abc_etc", + ":ability_runtime_page_node_info_abc_etc", + ":ability_runtime_view_data_abc_etc", ":ability_runtime_process_data_abc_etc", ":ability_runtime_process_information_abc_etc", ":ability_runtime_running_multi_appinfo_abc_etc", diff --git a/frameworks/ets/ets/application/AutoFillExtensionContext.ets b/frameworks/ets/ets/application/AutoFillExtensionContext.ets new file mode 100644 index 00000000000..1c02cf55a4b --- /dev/null +++ b/frameworks/ets/ets/application/AutoFillExtensionContext.ets @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import ExtensionContext from 'application.ExtensionContext'; +import type CustomData from 'application.CustomData'; +import AsyncCallbackWrapper from '../utils/AbilityUtils'; +import { BusinessError } from '@ohos.base'; + +export default class AutoFillExtensionContext extends ExtensionContext { + public nativeAutoFillExtensionContext : long = 0; + native nativeReloadInModal(customData: CustomData, callback: AsyncCallbackWrapper): void; + reloadInModal(customData: CustomData): Promise { + let p = new Promise((resolve: (data: undefined) => void, reject:(err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeReloadInModal(customData, myCall); + }); + }); + return p; + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AutoFillPopupConfig.ets b/frameworks/ets/ets/application/AutoFillPopupConfig.ets new file mode 100644 index 00000000000..a21cde8624c --- /dev/null +++ b/frameworks/ets/ets/application/AutoFillPopupConfig.ets @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default interface AutoFillPopupConfig { + popupSize?: PopupSize; + placement?: PopupPlacement; +} +export interface PopupSize { + width: number; + height: number; +} +export enum PopupPlacement { + LEFT = 0, + RIGHT = 1, + TOP = 2, + BOTTOM = 3, + TOP_LEFT = 4, + TOP_RIGHT = 5, + BOTTOM_LEFT = 6, + BOTTOM_RIGHT = 7, + LEFT_TOP = 8, + LEFT_BOTTOM = 9, + RIGHT_TOP = 10, + RIGHT_BOTTOM = 11, + NONE = 12 +} + +class AutoFillPopupConfigImpl implements AutoFillPopupConfig { + public popupSize?: PopupSize; + public placement?: PopupPlacement; +} +class PopupSizeImpl implements PopupSize { + public width: number; + public height: number; +} diff --git a/frameworks/ets/ets/application/AutoFillRect.ets b/frameworks/ets/ets/application/AutoFillRect.ets new file mode 100644 index 00000000000..cf635fee9d9 --- /dev/null +++ b/frameworks/ets/ets/application/AutoFillRect.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default interface AutoFillRect { + left: number; + top: number; + width: number; + height: number; +} + +class AutoFillRectImpl implements AutoFillRect { + public left: number; + public top: number; + public width: number; + public height: number; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AutoFillRequest.ets b/frameworks/ets/ets/application/AutoFillRequest.ets new file mode 100644 index 00000000000..fe657189307 --- /dev/null +++ b/frameworks/ets/ets/application/AutoFillRequest.ets @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AutoFillType } from 'application.AutoFillType'; +import type CustomData from 'application.CustomData'; +import type AutoFillPopupConfig from 'application.AutoFillPopupConfig'; +import type ViewData from 'application.ViewData'; + +export interface FillRequest { + type: AutoFillType; + viewData: ViewData; + customData: CustomData; + isPopup: boolean; +} +export interface SaveRequest { + viewData: ViewData; +} +export interface UpdateRequest { + viewData: ViewData; +} +export interface FillResponse { + viewData: ViewData; +} +export interface FillRequestCallback { + onSuccess(response: FillResponse): void; + onFailure(): void; + onCancel(fillContent?: string): void; + setAutoFillPopupConfig(autoFillPopupConfig: AutoFillPopupConfig): void; +} +export interface SaveRequestCallback { + onSuccess(): void; + onFailure(): void; +} + +class FillRequestInner implements FillRequest { + public type: AutoFillType = AutoFillType.UNSPECIFIED; + public viewData: ViewData = {}; + public customData: CustomData = {}; + public isPopup: boolean = false; +} +class SaveRequestInner implements SaveRequest { + public viewData: ViewData = {}; +} +class UpdateRequestInner implements UpdateRequest { + public viewData: ViewData = {}; +} +class FillResponseInner implements FillResponse { + public viewData: ViewData = {}; +} +class FillRequestCallbackInner implements FillRequestCallback { + public nativeSessionInfo : long = 0; + public nativeUiWindow : long = 0; + public native onSuccess(response: FillResponse): void; + public native onFailure(): void; + public native onCancel(fillContent?: string): void; + public native setAutoFillPopupConfig(autoFillPopupConfig: AutoFillPopupConfig): void; +} +class SaveRequestCallbackInner implements SaveRequestCallback { + public nativeSessionInfo : long = 0; + public nativeUiWindow : long = 0; + public native onSuccess(): void; + public native onFailure(): void; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AutoFillType.ets b/frameworks/ets/ets/application/AutoFillType.ets new file mode 100644 index 00000000000..4e63c75c662 --- /dev/null +++ b/frameworks/ets/ets/application/AutoFillType.ets @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export enum AutoFillType { + UNSPECIFIED = 0, + PASSWORD = 1, + USER_NAME = 2, + NEW_PASSWORD = 3, + FULL_STREET_ADDRESS = 4, + HOUSE_NUMBER = 5, + DISTRICT_ADDRESS = 6, + CITY_ADDRESS = 7, + PROVINCE_ADDRESS = 8, + COUNTRY_ADDRESS = 9, + PERSON_FULL_NAME = 10, + PERSON_LAST_NAME = 11, + PERSON_FIRST_NAME = 12, + PHONE_NUMBER = 13, + PHONE_COUNTRY_CODE = 14, + FULL_PHONE_NUMBER = 15, + EMAIL_ADDRESS = 16, + BANK_CARD_NUMBER = 17, + ID_CARD_NUMBER = 18, + NICKNAME = 24, + DETAIL_INFO_WITHOUT_STREET = 25, + FORMAT_ADDRESS = 26, + PASSPORT_NUMBER = 27, + VALIDITY = 28, + ISSUE_AT = 29, + ORGANIZATION = 30, + TAX_ID = 31, + ADDRESS_CITY_AND_STATE = 32, + FLIGHT_NUMBER = 33, + LICENSE_NUMBER = 34, + LICENSE_FILE_NUMBER = 35, + LICENSE_PLATE = 36, + ENGINE_NUMBER = 37, + LICENSE_CHASSIS_NUMBER = 38 +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/CustomData.ets b/frameworks/ets/ets/application/CustomData.ets new file mode 100644 index 00000000000..6d4c0a06111 --- /dev/null +++ b/frameworks/ets/ets/application/CustomData.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default interface CustomData { + data: Record; +} + +class CustomDataImpl implements CustomData { + public data: Record = {}; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/PageNodeInfo.ets b/frameworks/ets/ets/application/PageNodeInfo.ets new file mode 100644 index 00000000000..0a9bfb7892a --- /dev/null +++ b/frameworks/ets/ets/application/PageNodeInfo.ets @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AutoFillType } from 'application.AutoFillType'; +import type AutoFillRect from 'application.AutoFillRect'; + +export default interface PageNodeInfo { + id: number; + depth: number; + autoFillType: AutoFillType; + tag: string; + value: string; + placeholder?: string; + passwordRules?: string; + enableAutoFill: boolean; + rect: AutoFillRect; + isFocus: boolean; + metadata?: string; +} + +class PageNodeInfoImpl implements PageNodeInfo { + public id: number = 0; + public depth: number = 0; + public autoFillType: AutoFillType = AutoFillType.UNSPECIFIED; + public tag: string = ''; + public value: string = ''; + public placeholder?: string; + public passwordRules?: string; + public enableAutoFill: boolean = false; + public rect: AutoFillRect = {}; + public isFocus: boolean = false; + public metadata?: string; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/ViewData.ets b/frameworks/ets/ets/application/ViewData.ets new file mode 100644 index 00000000000..a7ff640e55d --- /dev/null +++ b/frameworks/ets/ets/application/ViewData.ets @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import PageNodeInfo from 'application.PageNodeInfo'; +import AutoFillRect from 'application.AutoFillRect'; + +export default interface ViewData { + bundleName: string; + moduleName: string; + abilityName: string; + pageUrl: string; + pageNodeInfos: Array; + pageRect: AutoFillRect; + isUserSelected: boolean; + isOtherAccount: boolean; +} + +class ViewDataImpl implements ViewData { + public bundleName: string = ''; + public moduleName: string = ''; + public abilityName: string = ''; + public pageUrl: string = ''; + public pageNodeInfos: Array = []; + public pageRect: AutoFillRect = {}; + public isUserSelected: boolean = false; + public isOtherAccount: boolean = false; +} \ No newline at end of file diff --git a/frameworks/native/ability/native/BUILD.gn b/frameworks/native/ability/native/BUILD.gn index cb53b53e804..c62b47c2d7a 100644 --- a/frameworks/native/ability/native/BUILD.gn +++ b/frameworks/native/ability/native/BUILD.gn @@ -2322,6 +2322,7 @@ ohos_shared_library("auto_fill_extension") { "${ability_runtime_native_path}/ability:ability_context_native", "${ability_runtime_native_path}/ability/native:ability_business_error", "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", ] external_deps = [ @@ -2343,6 +2344,10 @@ ohos_shared_library("auto_fill_extension") { sources += [ "${ability_runtime_native_path}/ability/native/auto_fill_extension_ability/auto_fill_extension.cpp", "${ability_runtime_native_path}/ability/native/auto_fill_extension_ability/auto_fill_extension_context.cpp", + "${ability_runtime_native_path}/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_context.cpp", + "${ability_runtime_native_path}/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.cpp", + "${ability_runtime_native_path}/ability/native/auto_fill_extension_ability/ets_fill_request_callback.cpp", + "${ability_runtime_native_path}/ability/native/auto_fill_extension_ability/ets_save_request_callback.cpp", "${ability_runtime_native_path}/ability/native/auto_fill_extension_ability/js_auto_fill_extension.cpp", "${ability_runtime_native_path}/ability/native/auto_fill_extension_ability/js_auto_fill_extension_context.cpp", "${ability_runtime_native_path}/ability/native/auto_fill_extension_ability/js_auto_fill_extension_util.cpp", diff --git a/frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_context.cpp b/frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_context.cpp new file mode 100644 index 00000000000..90381c2340d --- /dev/null +++ b/frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_context.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ets_auto_fill_extension_context.h" + +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "ets_extension_context.h" +#include "hilog_tag_wrapper.h" +#include "sts_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* AUTO_FILL_EXTENSION_CONTEXT_CLASS_NAME = + "Lapplication/AutoFillExtensionContext/AutoFillExtensionContext;"; +constexpr const char* CUSTOMDATA_DATA = "data"; +} + +EtsAutoFillExtensionContext &EtsAutoFillExtensionContext::GetInstance() +{ + static EtsAutoFillExtensionContext instance; + return instance; +} + +void EtsAutoFillExtensionContext::ReloadInModal(ani_env *env, ani_object object, ani_object customDataObj, + ani_object callback) +{ + GetInstance().OnReloadInModal(env, object, customDataObj, callback); +} + +void EtsAutoFillExtensionContext::OnReloadInModal(ani_env *env, ani_object object, ani_object customDataObj, + ani_object callback) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + return; + } + ani_object etsCustomData = AppExecFwk::GetPropertyValueByName(env, customDataObj, CUSTOMDATA_DATA); + CustomData customData; + if (etsCustomData == nullptr || !AppExecFwk::UnwrapWantParams(env, etsCustomData, customData.data)) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "Parse custom data failed"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return; + } + auto context = GetAutoFillExtensionContext(env, object); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null context"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + auto ret = context->ReloadInModal(customData); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "error is %{public}d", ret); + return; + } + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), nullptr); +} + +ani_object EtsAutoFillExtensionContext::SetAutoFillExtensionContext(ani_env *env, + const std::shared_ptr &context) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object contextObj = nullptr; + ani_field field = nullptr; + if (context == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null context"); + return nullptr; + } + if ((status = env->FindClass(AUTO_FILL_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find class status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find method status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "new object status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeAutoFillExtensionContext", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find nativeAutoFillExtensionContext: %{public}d", status); + return nullptr; + } + auto workContext = new (std::nothrow) std::weak_ptr(context); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "workContext nullptr"); + return nullptr; + } + ani_long nativeAutoFillExtensionContextLong = (ani_long)workContext; + if ((status = env->Object_SetField_Long(contextObj, field, nativeAutoFillExtensionContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeAutoFillExtensionContextLong: %{public}d", status); + delete workContext; + workContext = nullptr; + return nullptr; + } + return contextObj; +} + +std::shared_ptr EtsAutoFillExtensionContext::GetAutoFillExtensionContext(ani_env *env, + ani_object object) +{ + ani_long nativeAutoFillExtensionContextLong; + ani_class cls = nullptr; + ani_field contextField = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + return nullptr; + } + if ((status = env->FindClass(AUTO_FILL_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find class status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeAutoFillExtensionContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find nativeAutoFillExtensionContext: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(object, contextField, &nativeAutoFillExtensionContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeAutoFillExtensionContextLong: %{public}d", status); + return nullptr; + } + auto weakContext = reinterpret_cast*>(nativeAutoFillExtensionContextLong); + return weakContext != nullptr ? weakContext->lock() : nullptr; +} + +ani_object EtsAutoFillExtensionContext::CreateEtsAutoFillExtensionContext(ani_env *env, + const std::shared_ptr &context) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env or context"); + return nullptr; + } + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(AUTO_FILL_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find class status: %{public}d", status); + return nullptr; + } + std::array functions = { + ani_native_function { "nativeReloadInModal", + "Lapplication/CustomData/CustomData;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAutoFillExtensionContext::ReloadInModal) }, + }; + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "bind method status : %{public}d", status); + return nullptr; + } + ani_object contextObj = SetAutoFillExtensionContext(env, context); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null contextObj"); + return nullptr; + } + OHOS::AbilityRuntime::CreatEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo()); + return contextObj; +} +} +} \ No newline at end of file diff --git a/frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.cpp b/frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.cpp new file mode 100644 index 00000000000..a7906f00087 --- /dev/null +++ b/frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ets_auto_fill_extension_util.h" + +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char *VIEW_DATA_BUNDLE_NAME = "bundleName"; +constexpr const char *VIEW_DATA_MODULE_NAME = "moduleName"; +constexpr const char *VIEW_DATA_ABILITY_NAME = "abilityName"; +constexpr const char *VIEW_DATA_PAGEURL = "pageUrl"; +constexpr const char *VIEW_DATA_USER_SELECTED = "isUserSelected"; +constexpr const char *VIEW_DATA_OTHER_ACCOUNT = "isOtherAccount"; +constexpr const char *VIEW_DATA_PAGE_NODE_INFOS = "pageNodeInfos"; +constexpr const char *VIEW_DATA_VIEW_DATA = "viewData"; +constexpr const char *VIEW_DATA_PAGE_RECT = "pageRect"; +constexpr const char *PAGE_INFO_ID = "id"; +constexpr const char *PAGE_INFO_DEPTH = "depth"; +constexpr const char *PAGE_INFO_AUTOFILLTYPE = "autoFillType"; +constexpr const char *PAGE_INFO_TAG = "tag"; +constexpr const char *PAGE_INFO_VALUE = "value"; +constexpr const char *PAGE_INFO_PLACEHOLDER = "placeholder"; +constexpr const char *PAGE_INFO_META_DATA = "metadata"; +constexpr const char *PAGE_INFO_PASSWORDRULES = "passwordRules"; +constexpr const char *PAGE_INFO_ENABLEAUTOFILL = "enableAutoFill"; +constexpr const char *PAGE_INFO_IS_FOCUS = "isFocus"; +constexpr const char *PAGE_INFO_PAGE_NODE_RECT = "rect"; +constexpr const char *RECT_POSITION_LEFT = "left"; +constexpr const char *RECT_POSITION_TOP = "top"; +constexpr const char *RECT_WIDTH = "width"; +constexpr const char *RECT_HEIGHT = "height"; +constexpr uint32_t PAGE_NODE_COUNT_MAX = 100; +} // namespace + +void EtsAutoFillExtensionUtil::UnwrapViewData(ani_env *env, const ani_object object, AbilityBase::ViewData &viewData) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + ani_object etsViewData = AppExecFwk::GetPropertyValueByName(env, object, VIEW_DATA_VIEW_DATA); + if (etsViewData == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null etsViewData"); + return; + } + UnwrapViewDataString(env, etsViewData, viewData); + ani_boolean isUserSelected = false; + if (AppExecFwk::IsExistsProperty(env, etsViewData, VIEW_DATA_USER_SELECTED)) { + isUserSelected = AppExecFwk::GetBoolOrUndefined(env, etsViewData, VIEW_DATA_USER_SELECTED); + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "isUserSelected:%{public}hhu", isUserSelected); + viewData.isUserSelected = isUserSelected; + } + ani_boolean isOtherAccount = false; + if (AppExecFwk::IsExistsProperty(env, etsViewData, VIEW_DATA_OTHER_ACCOUNT)) { + isOtherAccount = AppExecFwk::GetBoolOrUndefined(env, etsViewData, VIEW_DATA_OTHER_ACCOUNT); + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "isOtherAccount:%{public}hhu", isOtherAccount); + viewData.isOtherAccount = isOtherAccount; + } + ani_object etsPageNodeInfos = AppExecFwk::GetPropertyValueByName(env, etsViewData, VIEW_DATA_PAGE_NODE_INFOS); + if (etsPageNodeInfos != nullptr) { + ani_double etsProCount = 0.0; + if (!AppExecFwk::GetDoublePropertyValue(env, etsViewData, VIEW_DATA_PAGE_NODE_INFOS, etsProCount)) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "get length fail"); + return; + } + for (uint32_t index = 0; index < static_cast(etsProCount) && index < PAGE_NODE_COUNT_MAX; index++) { + ani_ref etsNode = nullptr; + if (ANI_OK != (env->Object_CallMethodByName_Ref(etsViewData, "$_get", "I:Lstd/core/Object;", &etsNode, + (ani_int)index))) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "Object_CallMethodByName_Ref _get Failed"); + return; + } + AbilityBase::PageNodeInfo node; + UnwrapPageNodeInfo(env, static_cast(etsNode), node); + viewData.nodes.emplace_back(node); + } + } + ani_object etsPageRect = AppExecFwk::GetPropertyValueByName(env, etsViewData, VIEW_DATA_PAGE_RECT); + if (etsPageRect != nullptr) { + UnwrapRectData(env, etsPageRect, viewData.pageRect); + } +} + +void EtsAutoFillExtensionUtil::UnwrapPageNodeInfo(ani_env *env, const ani_object object, + AbilityBase::PageNodeInfo &node) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + ani_double id = 0.0; + if (AppExecFwk::GetDoubleOrUndefined(env, object, PAGE_INFO_ID, id)) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "id:%{public}f", id); + node.id = id; + } + ani_double depth = 0.0; + if (AppExecFwk::GetDoubleOrUndefined(env, object, PAGE_INFO_DEPTH, depth)) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "depth:%{public}f", depth); + node.depth = depth; + } + ani_double autoFillType = 0.0; + if (AppExecFwk::GetDoubleOrUndefined(env, object, PAGE_INFO_AUTOFILLTYPE, autoFillType)) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "autoFillType:%{public}f", autoFillType); + node.autoFillType = static_cast(autoFillType); + } + UnwrapPageNodeInfoString(env, object, node); + ani_boolean enableAutoFill = false; + if (AppExecFwk::IsExistsProperty(env, object, PAGE_INFO_ENABLEAUTOFILL)) { + enableAutoFill = AppExecFwk::GetBoolOrUndefined(env, object, PAGE_INFO_ENABLEAUTOFILL); + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "enableAutoFill:%{public}hhu", enableAutoFill); + node.enableAutoFill = enableAutoFill; + } + ani_object etsRect = AppExecFwk::GetPropertyValueByName(env, object, PAGE_INFO_PAGE_NODE_RECT); + if (etsRect != nullptr) { + UnwrapRectData(env, etsRect, node.rect); + } + ani_boolean isFocus = false; + if (AppExecFwk::IsExistsProperty(env, object, PAGE_INFO_IS_FOCUS)) { + isFocus = AppExecFwk::GetBoolOrUndefined(env, object, PAGE_INFO_IS_FOCUS); + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "isFocus:%{public}hhu", isFocus); + node.isFocus = isFocus; + } +} + +void EtsAutoFillExtensionUtil::UnwrapRectData(ani_env *env, const ani_object object, AbilityBase::Rect &rect) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + ani_double position = 0.0; + if (AppExecFwk::GetDoubleOrUndefined(env, object, RECT_POSITION_LEFT, position)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "left:%{public}f", position); + rect.left = position; + } + if (AppExecFwk::GetDoubleOrUndefined(env, object, RECT_POSITION_TOP, position)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "top:%{public}f", position); + rect.top = position; + } + if (AppExecFwk::GetDoubleOrUndefined(env, object, RECT_WIDTH, position)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "width:%{public}f", position); + rect.width = position; + } + if (AppExecFwk::GetDoubleOrUndefined(env, object, RECT_HEIGHT, position)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "height:%{public}f", position); + rect.height = position; + } +} + +void EtsAutoFillExtensionUtil::UnwrapFillResponse(ani_env *env, const ani_object object, FillResponse &response) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + UnwrapViewData(env, object, response.viewData); +} + +void EtsAutoFillExtensionUtil::UnwrapPopupSize(ani_env *env, const ani_object object, PopupSize &popupSize) +{ + ani_double width = 0.0; + if (AppExecFwk::GetDoubleOrUndefined(env, object, RECT_WIDTH, width)) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "width:%{public}f", width); + popupSize.width = width; + } + ani_double height = 0.0; + if (AppExecFwk::GetDoubleOrUndefined(env, object, RECT_HEIGHT, height)) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "height:%{public}f", height); + popupSize.height = height; + } +} + +void EtsAutoFillExtensionUtil::UnwrapViewDataString(ani_env *env, const ani_object object, + AbilityBase::ViewData &viewData) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + std::string bundleName = ""; + if (AppExecFwk::GetStringOrUndefined(env, object, VIEW_DATA_BUNDLE_NAME, bundleName)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "The parsed bundleName part %{public}s", bundleName.c_str()); + viewData.bundleName = bundleName; + } + std::string moduleName = ""; + if (AppExecFwk::GetStringOrUndefined(env, object, VIEW_DATA_MODULE_NAME, moduleName)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "The parsed moduleName part %{public}s", moduleName.c_str()); + viewData.moduleName = moduleName; + } + std::string abilityName = ""; + if (AppExecFwk::GetStringOrUndefined(env, object, VIEW_DATA_ABILITY_NAME, abilityName)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "The parsed abilityName part %{public}s", abilityName.c_str()); + viewData.abilityName = abilityName; + } + std::string pageUrl = ""; + if (AppExecFwk::GetStringOrUndefined(env, object, VIEW_DATA_PAGEURL, pageUrl)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "The parsed pageUrl part %{public}s", pageUrl.c_str()); + viewData.pageUrl = pageUrl; + } +} + +void EtsAutoFillExtensionUtil::UnwrapPageNodeInfoString(ani_env *env, const ani_object object, + AbilityBase::PageNodeInfo &node) +{ + std::string tag = ""; + if (AppExecFwk::GetStringOrUndefined(env, object, PAGE_INFO_TAG, tag)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "The parsed tag part %{public}s", tag.c_str()); + node.tag = tag; + } + std::string value = ""; + if (AppExecFwk::GetStringOrUndefined(env, object, PAGE_INFO_VALUE, value)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "The parsed value part %{public}s", value.c_str()); + node.value = value; + } + std::string passwordRules = ""; + if (AppExecFwk::GetStringOrUndefined(env, object, PAGE_INFO_PASSWORDRULES, passwordRules)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "The parsed passwordRules part %{public}s", passwordRules.c_str()); + node.passwordRules = passwordRules; + } + std::string placeholder = ""; + if (AppExecFwk::GetStringOrUndefined(env, object, PAGE_INFO_PLACEHOLDER, placeholder)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "The parsed placeholder part %{public}s", placeholder.c_str()); + node.placeholder = placeholder; + } + std::string metadata = ""; + if (AppExecFwk::GetStringOrUndefined(env, object, PAGE_INFO_META_DATA, metadata)) { + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "The parsed metadata part %{public}s", metadata.c_str()); + node.metadata = metadata; + } +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/auto_fill_extension_ability/ets_fill_request_callback.cpp b/frameworks/native/ability/native/auto_fill_extension_ability/ets_fill_request_callback.cpp new file mode 100644 index 00000000000..2d37c0a6aac --- /dev/null +++ b/frameworks/native/ability/native/auto_fill_extension_ability/ets_fill_request_callback.cpp @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ets_fill_request_callback.h" + +#include "ability_manager_client.h" +#include "ani_common_util.h" +#include "hilog_tag_wrapper.h" +#include "int_wrapper.h" +#include "ipc_skeleton.h" +#include "sts_error_utils.h" +#include "tokenid_kit.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char *WANT_PARAMS_VIEW_DATA = "ohos.ability.params.viewData"; +constexpr const char *WANT_PARAMS_AUTO_FILL_CMD = "ohos.ability.params.autoFillCmd"; +constexpr const char *WANT_PARAMS_AUTO_FILL_CMD_AUTOFILL = "autofill"; +constexpr const char *WANT_PARAMS_UPDATE_POPUP_WIDTH = "ohos.ability.params.popupWidth"; +constexpr const char *WANT_PARAMS_UPDATE_POPUP_HEIGHT = "ohos.ability.params.popupHeight"; +constexpr const char *WANT_PARAMS_UPDATE_POPUP_PLACEMENT = "ohos.ability.params.popupPlacement"; +constexpr const char *CONFIG_POPUP_SIZE = "popupSize"; +constexpr const char *CONFIG_POPUP_PLACEMENT = "placement"; +constexpr const char *WANT_PARAMS_FILL_CONTENT = "ohos.ability.params.fillContent"; +constexpr const char *ERROR_MSG_INVALID_EMPTY = "JsonString is empty."; +constexpr const char *FILL_REQUEST_CALL_BACK_CLASS_NAME = "Lapplication/AutoFillRequest/FillRequestCallbackInner;"; +} + +EtsFillRequestCallback &EtsFillRequestCallback::GetInstance() +{ + static EtsFillRequestCallback instance; + return instance; +} + +ani_object EtsFillRequestCallback::SetSessionInfoAndWindow(ani_env *env, const sptr &sessionInfo, + const sptr &uiWindow) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = nullptr; + ani_field field = nullptr; + if (sessionInfo == nullptr || uiWindow == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null sessionInfo or uiWindow"); + return nullptr; + } + if ((status = env->FindClass(FILL_REQUEST_CALL_BACK_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find class status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find method status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "new object status: %{public}d", status); + return nullptr; + } + SetField(env, object, cls, field, sessionInfo, uiWindow); + return object; +} + +void EtsFillRequestCallback::SetField(ani_env *env, ani_object object, ani_class cls, ani_field field, + const sptr &sessionInfo, const sptr &uiWindow) +{ + ani_status status = ANI_ERROR; + if ((status = env->Class_FindField(cls, "nativeSessionInfo", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find nativeSessionInfo: %{public}d", status); + return; + } + auto nativeSessionInfo = new (std::nothrow) sptr(sessionInfo); + if (nativeSessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeSessionInfo nullptr"); + return; + } + ani_long nativeSessionInfoLong = (ani_long)nativeSessionInfo; + if ((status = env->Object_SetField_Long(object, field, nativeSessionInfoLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeSessionInfoLong: %{public}d", status); + delete nativeSessionInfo; + nativeSessionInfo = nullptr; + return; + } + if ((status = env->Class_FindField(cls, "nativeUiWindow", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find nativeUiWindow: %{public}d", status); + return; + } + auto nativeUiWindow = new (std::nothrow) sptr(uiWindow); + if (nativeUiWindow == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeUiWindow nullptr"); + return; + } + ani_long nativeUiWindowLong = (ani_long)nativeUiWindow; + if ((status = env->Object_SetField_Long(object, field, nativeUiWindowLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeUiWindowLong: %{public}d", status); + delete nativeUiWindow; + nativeUiWindow = nullptr; + return; + } +} + +sptr EtsFillRequestCallback::GetSessionInfo(ani_env *env, ani_object object) +{ + ani_long nativeSessionInfoLong; + ani_class cls = nullptr; + ani_field field = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + return nullptr; + } + if ((status = env->FindClass(FILL_REQUEST_CALL_BACK_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find class status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeSessionInfo", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find field: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(object, field, &nativeSessionInfoLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeSessionInfoLong: %{public}d", status); + return nullptr; + } + auto nativeSessionInfoPtr = reinterpret_cast(nativeSessionInfoLong); + auto nativeSessionInfo = sptr(nativeSessionInfoPtr); + return nativeSessionInfo != nullptr ? nativeSessionInfo : nullptr; +} + +sptr EtsFillRequestCallback::GetWindow(ani_env *env, ani_object object) +{ + ani_long nativeUiWindowLong; + ani_class cls = nullptr; + ani_field field = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + return nullptr; + } + if ((status = env->FindClass(FILL_REQUEST_CALL_BACK_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find class status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeUiWindow", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find field: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(object, field, &nativeUiWindowLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeUiWindowLong: %{public}d", status); + return nullptr; + } + auto nativeUiWindowPtr = reinterpret_cast(nativeUiWindowLong); + auto nativeUiWindow = sptr(nativeUiWindowPtr); + return nativeUiWindow != nullptr ? nativeUiWindow : nullptr; +} + +void EtsFillRequestCallback::FillRequestSuccess(ani_env *env, ani_object object, ani_object responseObj) +{ + GetInstance().OnFillRequestSuccess(env, object, responseObj); +} + +void EtsFillRequestCallback::FillRequestFailed(ani_env *env, ani_object object) +{ + GetInstance().OnFillRequestFailed(env, object); +} + +void EtsFillRequestCallback::FillRequestCanceled(ani_env *env, ani_object object, ani_object fillContentObj) +{ + GetInstance().OnFillRequestCanceled(env, object, fillContentObj); +} + +void EtsFillRequestCallback::FillRequestAutoFillPopupConfig(ani_env *env, ani_object object, + ani_object autoFillPopupConfigObj) +{ + GetInstance().OnFillRequestAutoFillPopupConfig(env, object, autoFillPopupConfigObj); +} + +void EtsFillRequestCallback::OnFillRequestSuccess(ani_env *env, ani_object object, ani_object responseObj) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + SendResultCodeAndViewData(env, object, + EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_FAILED_INVALID_PARAM, ""); + return; + } + FillResponse response; + EtsAutoFillExtensionUtil::UnwrapFillResponse(env, responseObj, response); + std::string jsonString = response.viewData.ToJsonString(); + if (jsonString.empty()) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "empty jsonString"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + SendResultCodeAndViewData(env, object, + EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_FAILED_INVALID_PARAM, ""); + return; + } + SendResultCodeAndViewData(env, object, EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_SUCESS, jsonString); +} + +void EtsFillRequestCallback::OnFillRequestFailed(ani_env *env, ani_object object) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + SendResultCodeAndViewData(env, object, + EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_FAILED_INVALID_PARAM, ""); + return; + } + SendResultCodeAndViewData(env, object, EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_FAILED, ""); +} + +void EtsFillRequestCallback::OnFillRequestCanceled(ani_env *env, ani_object object, ani_object fillContentObj) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + SendResultCodeAndViewData(env, object, + EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_FAILED_INVALID_PARAM, ""); + return; + } + std::string jsonString = ""; + ani_status status = ANI_OK; + ani_boolean isFillContentUndefined; + if ((status = env->Reference_IsUndefined(fillContentObj, &isFillContentUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "Falied to check undefinde status: %{public}d", status); + SendResultCodeAndViewData(env, object, + EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_FAILED_INVALID_PARAM, ""); + return; + } + if (!isFillContentUndefined) { + if (!AppExecFwk::GetStdString(env, reinterpret_cast(fillContentObj), jsonString)) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "empty jsonString"); + ThrowStsError(env, static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + ERROR_MSG_INVALID_EMPTY); + SendResultCodeAndViewData(env, object, + EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_FAILED_INVALID_PARAM, ""); + return; + } + } + SendResultCodeAndViewData(env, object, EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_CANCEL, jsonString); +} + +void EtsFillRequestCallback::OnFillRequestAutoFillPopupConfig(ani_env *env, ani_object object, + ani_object autoFillPopupConfigObj) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "Non-system app forbidden to call"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return; + } + auto uiWindow = GetWindow(env, object); + if (uiWindow == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null uiWindow"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return; + } + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + return; + } + AAFwk::WantParams wantParams; + wantParams.SetParam(WANT_PARAMS_AUTO_FILL_CMD, AAFwk::Integer::Box(AutoFillCommand::RESIZE)); + auto isValueChanged = SetPopupConfigToWantParams(env, autoFillPopupConfigObj, wantParams); + if (isValueChanged) { + auto ret = uiWindow->TransferExtensionData(wantParams); + if (ret != Rosen::WMError::WM_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "Transfer ability result failed"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + } + } +} + +bool EtsFillRequestCallback::SetPopupConfigToWantParams(ani_env *env, ani_object autoFillPopupConfigObj, + AAFwk::WantParams& wantParams) +{ + ani_object etsValue = nullptr; + bool isValueChanged = false; + etsValue = AppExecFwk::GetPropertyValueByName(env, autoFillPopupConfigObj, CONFIG_POPUP_SIZE); + if (etsValue) { + PopupSize popupSize; + EtsAutoFillExtensionUtil::UnwrapPopupSize(env, etsValue, popupSize); + wantParams.SetParam(WANT_PARAMS_UPDATE_POPUP_WIDTH, AAFwk::Integer::Box(popupSize.width)); + wantParams.SetParam(WANT_PARAMS_UPDATE_POPUP_HEIGHT, AAFwk::Integer::Box(popupSize.height)); + isValueChanged = true; + } + int popupPlacement = 0; + if (AppExecFwk::GetIntByName(env, autoFillPopupConfigObj, CONFIG_POPUP_PLACEMENT, popupPlacement)) { + wantParams.SetParam(WANT_PARAMS_UPDATE_POPUP_PLACEMENT, AAFwk::Integer::Box(popupPlacement)); + isValueChanged = true; + } + return isValueChanged; +} + +void EtsFillRequestCallback::SendResultCodeAndViewData(ani_env *env, ani_object object, + const EtsAutoFillExtensionUtil::AutoFillResultCode &resultCode, const std::string &etsString) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + auto uiWindow = GetWindow(env, object); + if (uiWindow == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null uiWindow"); + return; + } + + AAFwk::Want want; + if (resultCode == EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_SUCESS) { + want.SetParam(WANT_PARAMS_VIEW_DATA, etsString); + want.SetParam(WANT_PARAMS_AUTO_FILL_CMD, WANT_PARAMS_AUTO_FILL_CMD_AUTOFILL); + } + + if (resultCode == EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_CANCEL) { + want.SetParam(WANT_PARAMS_FILL_CONTENT, etsString); + } + + auto ret = uiWindow->TransferAbilityResult(resultCode, want); + if (ret != Rosen::WMError::WM_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "TransferAbilityResult failed"); + return; + } + + auto sessionInfo = GetSessionInfo(env, object); + if (sessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null sessionInfo"); + return; + } + + auto errorCode = AAFwk::AbilityManagerClient::GetInstance()->TerminateUIExtensionAbility(sessionInfo); + if (errorCode != ERR_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "TerminateUIExtensionAbility error: %{public}d", errorCode); + } +} + +ani_object EtsFillRequestCallback::CreateEtsFillRequestCallback(ani_env *env, + const sptr &sessionInfo, const sptr &uiWindow) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + return nullptr; + } + if (sessionInfo == nullptr || uiWindow == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null sessionInfo or uiWindow"); + return nullptr; + } + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(FILL_REQUEST_CALL_BACK_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find class status: %{public}d", status); + return nullptr; + } + std::array functions = { + ani_native_function { "onSuccess", "Lapplication/AutoFillRequest/FillResponse;:V", + reinterpret_cast(EtsFillRequestCallback::FillRequestSuccess) }, + ani_native_function { "onFailure", ":V", + reinterpret_cast(EtsFillRequestCallback::FillRequestFailed) }, + ani_native_function { "onCancel", "Lstd/core/String;:V", + reinterpret_cast(EtsFillRequestCallback::FillRequestCanceled) }, + ani_native_function { "setAutoFillPopupConfig", "Lapplication/AutoFillRequest/AutoFillPopupConfig;:V", + reinterpret_cast(EtsFillRequestCallback::FillRequestAutoFillPopupConfig) }, + }; + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "bind method status : %{public}d", status); + return nullptr; + } + ani_object object = SetSessionInfoAndWindow(env, sessionInfo, uiWindow); + if (object == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null object"); + return nullptr; + } + return object; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/auto_fill_extension_ability/ets_save_request_callback.cpp b/frameworks/native/ability/native/auto_fill_extension_ability/ets_save_request_callback.cpp new file mode 100644 index 00000000000..5564118b674 --- /dev/null +++ b/frameworks/native/ability/native/auto_fill_extension_ability/ets_save_request_callback.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ets_save_request_callback.h" + +#include "ability_manager_client.h" +#include "ani_common_util.h" +#include "hilog_tag_wrapper.h" +#include "int_wrapper.h" +#include "ipc_skeleton.h" +#include "sts_error_utils.h" +#include "tokenid_kit.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char *SAVE_REQUEST_CALL_BACK_CLASS_NAME = "Lapplication/AutoFillRequest/SaveRequestCallbackInner;"; +} + +void EtsSaveRequestCallback::SaveRequestSuccess(ani_env *env, ani_object object) +{ + GetInstance().OnSaveRequestSuccess(env, object); +} + +void EtsSaveRequestCallback::SaveRequestFailed(ani_env *env, ani_object object) +{ + GetInstance().OnSaveRequestFailed(env, object); +} + +void EtsSaveRequestCallback::OnSaveRequestSuccess(ani_env *env, ani_object object) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + SendResultCodeAndViewData(env, object, + EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_FAILED_INVALID_PARAM); + return; + } + SendResultCodeAndViewData(env, object, EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_SUCESS); +} + +void EtsSaveRequestCallback::OnSaveRequestFailed(ani_env *env, ani_object object) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + SendResultCodeAndViewData(env, object, + EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_FAILED_INVALID_PARAM); + return; + } + SendResultCodeAndViewData(env, object, EtsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_FAILED); +} + +void EtsSaveRequestCallback::SendResultCodeAndViewData(ani_env *env, ani_object object, + const EtsAutoFillExtensionUtil::AutoFillResultCode &resultCode) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + auto uiWindow = GetWindow(env, object); + if (uiWindow == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null uiWindow"); + return; + } + + AAFwk::Want want; + auto ret = uiWindow->TransferAbilityResult(resultCode, want); + if (ret != Rosen::WMError::WM_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "TransferAbilityResult failed"); + return; + } + + auto sessionInfo = GetSessionInfo(env, object); + auto errorCode = AAFwk::AbilityManagerClient::GetInstance()->TerminateUIExtensionAbility(sessionInfo); + if (errorCode != ERR_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "TerminateUIExtensionAbility error: %{public}d", errorCode); + } +} + +EtsSaveRequestCallback &EtsSaveRequestCallback::GetInstance() +{ + static EtsSaveRequestCallback instance; + return instance; +} + +ani_object EtsSaveRequestCallback::SetSessionInfoAndWindow(ani_env *env, const sptr &sessionInfo, + const sptr &uiWindow) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = nullptr; + ani_field field = nullptr; + if (sessionInfo == nullptr || uiWindow == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null sessionInfo or uiWindow"); + return nullptr; + } + if ((status = env->FindClass(SAVE_REQUEST_CALL_BACK_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find class status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find method status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "new object status: %{public}d", status); + return nullptr; + } + SetField(env, object, cls, field, sessionInfo, uiWindow); + return object; +} + +void EtsSaveRequestCallback::SetField(ani_env *env, ani_object object, ani_class cls, ani_field field, + const sptr &sessionInfo, const sptr &uiWindow) +{ + ani_status status = ANI_ERROR; + if ((status = env->Class_FindField(cls, "nativeSessionInfo", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find nativeSessionInfo: %{public}d", status); + return; + } + auto nativeSessionInfo = new (std::nothrow) sptr(sessionInfo); + if (nativeSessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeSessionInfo nullptr"); + return; + } + ani_long nativeSessionInfoLong = (ani_long)nativeSessionInfo; + if ((status = env->Object_SetField_Long(object, field, nativeSessionInfoLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeSessionInfoLong: %{public}d", status); + delete nativeSessionInfo; + nativeSessionInfo = nullptr; + return; + } + if ((status = env->Class_FindField(cls, "nativeUiWindow", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find nativeUiWindow: %{public}d", status); + return; + } + auto nativeUiWindow = new (std::nothrow) sptr(uiWindow); + if (nativeUiWindow == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeUiWindow nullptr"); + return; + } + ani_long nativeUiWindowLong = (ani_long)nativeUiWindow; + if ((status = env->Object_SetField_Long(object, field, nativeUiWindowLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeUiWindowLong: %{public}d", status); + delete nativeUiWindow; + nativeUiWindow = nullptr; + return; + } +} + +sptr EtsSaveRequestCallback::GetSessionInfo(ani_env *env, ani_object object) +{ + ani_long nativeSessionInfoLong; + ani_class cls = nullptr; + ani_field field = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + return nullptr; + } + if ((status = env->FindClass(SAVE_REQUEST_CALL_BACK_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find class status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeSessionInfo", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find field: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(object, field, &nativeSessionInfoLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeSessionInfoLong: %{public}d", status); + return nullptr; + } + auto nativeSessionInfoPtr = reinterpret_cast(nativeSessionInfoLong); + auto nativeSessionInfo = sptr(nativeSessionInfoPtr); + return nativeSessionInfo != nullptr ? nativeSessionInfo : nullptr; +} + +sptr EtsSaveRequestCallback::GetWindow(ani_env *env, ani_object object) +{ + ani_long nativeUiWindowLong; + ani_class cls = nullptr; + ani_field field = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + return nullptr; + } + if ((status = env->FindClass(SAVE_REQUEST_CALL_BACK_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find class status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeUiWindow", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find field: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(object, field, &nativeUiWindowLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "nativeUiWindowLong: %{public}d", status); + return nullptr; + } + auto nativeUiWindowPtr = reinterpret_cast(nativeUiWindowLong); + auto nativeUiWindow = sptr(nativeUiWindowPtr); + return nativeUiWindow != nullptr ? nativeUiWindow : nullptr; +} + +ani_object EtsSaveRequestCallback::CreateEtsSaveRequestCallback(ani_env *env, + const sptr &sessionInfo, const sptr &uiWindow) +{ + TAG_LOGD(AAFwkTag::AUTOFILL_EXT, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + return nullptr; + } + if (sessionInfo == nullptr || uiWindow == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null sessionInfo or uiWindow"); + return nullptr; + } + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(SAVE_REQUEST_CALL_BACK_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "find class status: %{public}d", status); + return nullptr; + } + std::array functions = { + ani_native_function { "onSuccess", ":V", + reinterpret_cast(EtsSaveRequestCallback::SaveRequestSuccess) }, + ani_native_function { "onFailure", ":V", + reinterpret_cast(EtsSaveRequestCallback::SaveRequestFailed) }, + }; + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "bind method status : %{public}d", status); + return nullptr; + } + ani_object object = SetSessionInfoAndWindow(env, sessionInfo, uiWindow); + if (object == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null object"); + return nullptr; + } + return object; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_context.h b/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_context.h new file mode 100644 index 00000000000..f177b052c86 --- /dev/null +++ b/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_context.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_AUTO_FILL_EXTENSION_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_ETS_AUTO_FILL_EXTENSION_CONTEXT_H + +#include "auto_fill_extension_context.h" +#include "ets_auto_fill_extension_util.h" +#include "sts_runtime.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsAutoFillExtensionContext final { +public: + explicit EtsAutoFillExtensionContext() = default; + virtual ~EtsAutoFillExtensionContext() = default; + + static EtsAutoFillExtensionContext &GetInstance(); + static void ReloadInModal(ani_env *env, ani_object object, ani_object customDataObj, ani_object callback); + static ani_object SetAutoFillExtensionContext(ani_env *env, + const std::shared_ptr &context); + static std::shared_ptr GetAutoFillExtensionContext(ani_env *env, ani_object object); + static ani_object CreateEtsAutoFillExtensionContext(ani_env *env, + const std::shared_ptr &context); + +private: + void OnReloadInModal(ani_env *env, ani_object object, ani_object customDataObj, ani_object callback); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_AUTO_FILL_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.h b/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.h new file mode 100644 index 00000000000..2b61b83bd62 --- /dev/null +++ b/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_AUTO_FILL_EXTENSION_UTIL_H +#define OHOS_ABILITY_RUNTIME_ETS_AUTO_FILL_EXTENSION_UTIL_H + +#include "session_info.h" +#include "sts_runtime.h" +#include "view_data.h" + +namespace OHOS { +namespace AbilityRuntime { +struct FillResponse { + AbilityBase::ViewData viewData; +}; + +struct PopupSize { + int32_t width = 0; + int32_t height = 0; +}; + +enum AutoFillCommand { + NONE, + FILL, + SAVE, + UPDATE, + RESIZE, + INPUT, + RELOAD_IN_MODAL +}; + +struct CustomData { + AAFwk::WantParams data; +}; + +class EtsAutoFillExtensionUtil { +public: + explicit EtsAutoFillExtensionUtil(const std::unique_ptr &runtime); + virtual ~EtsAutoFillExtensionUtil(); + static void UnwrapViewData(ani_env *env, const ani_object object, AbilityBase::ViewData &viewData); + static void UnwrapPageNodeInfo(ani_env *env, const ani_object object, AbilityBase::PageNodeInfo &node); + static void UnwrapRectData(ani_env *env, const ani_object object, AbilityBase::Rect &rect); + static void UnwrapFillResponse(ani_env *env, const ani_object object, FillResponse &response); + static void UnwrapPopupSize(ani_env *env, const ani_object object, PopupSize &popupSize); + + enum AutoFillResultCode { + CALLBACK_SUCESS = 0, + CALLBACK_FAILED, + CALLBACK_CANCEL, + CALLBACK_REMOVE_TIME_OUT, + CALLBACK_FAILED_INVALID_PARAM, + }; + +private: + static void UnwrapViewDataString(ani_env *env, const ani_object object, AbilityBase::ViewData &viewData); + static void UnwrapPageNodeInfoString(ani_env *env, const ani_object object, AbilityBase::PageNodeInfo &node); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_AUTO_FILL_EXTENSION_UTIL_H \ No newline at end of file diff --git a/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_fill_request_callback.h b/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_fill_request_callback.h new file mode 100644 index 00000000000..08ff375ff41 --- /dev/null +++ b/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_fill_request_callback.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_FILL_REQUEST_CALLBACK_H +#define OHOS_ABILITY_RUNTIME_ETS_FILL_REQUEST_CALLBACK_H + +#include "ets_auto_fill_extension_util.h" +#include "session_info.h" +#include "sts_runtime.h" +#include "want.h" +#include "window.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsFillRequestCallback { +public: + EtsFillRequestCallback() = default; + virtual ~EtsFillRequestCallback() = default; + + static EtsFillRequestCallback &GetInstance(); + static ani_object SetSessionInfoAndWindow(ani_env *env, const sptr &sessionInfo, + const sptr &uiWindow); + static void SetField(ani_env *env, ani_object object, ani_class cls, ani_field field, + const sptr &sessionInfo, const sptr &uiWindow); + static sptr GetSessionInfo(ani_env *env, ani_object object); + static sptr GetWindow(ani_env *env, ani_object object); + static ani_object CreateEtsFillRequestCallback(ani_env *env, const sptr &sessionInfo, + const sptr &uiWindow); + static void FillRequestSuccess(ani_env *env, ani_object object, ani_object responseObj); + static void FillRequestFailed(ani_env *env, ani_object object); + static void FillRequestCanceled(ani_env *env, ani_object object, ani_object fillContentObj); + static void FillRequestAutoFillPopupConfig(ani_env *env, ani_object object, ani_object autoFillPopupConfigObj); + +private: + void OnFillRequestSuccess(ani_env *env, ani_object object, ani_object responseObj); + void OnFillRequestFailed(ani_env *env, ani_object object); + void OnFillRequestCanceled(ani_env *env, ani_object object, ani_object fillContentObj); + void OnFillRequestAutoFillPopupConfig(ani_env *env, ani_object object, ani_object autoFillPopupConfigObj); + bool SetPopupConfigToWantParams(ani_env *env, ani_object autoFillPopupConfigObj, AAFwk::WantParams& wantParams); + void SendResultCodeAndViewData(ani_env *env, ani_object object, + const EtsAutoFillExtensionUtil::AutoFillResultCode &resultCode, const std::string &etsString); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_FILL_REQUEST_CALLBACK_H \ No newline at end of file diff --git a/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_save_request_callback.h b/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_save_request_callback.h new file mode 100644 index 00000000000..45d53884a42 --- /dev/null +++ b/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_save_request_callback.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_SAVE_REQUEST_CALLBACK_H +#define OHOS_ABILITY_RUNTIME_ETS_SAVE_REQUEST_CALLBACK_H + +#include "ets_auto_fill_extension_util.h" +#include "session_info.h" +#include "sts_runtime.h" +#include "want.h" +#include "window.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsSaveRequestCallback { +public: + EtsSaveRequestCallback() = default; + virtual ~EtsSaveRequestCallback() = default; + + static EtsSaveRequestCallback &GetInstance(); + static ani_object SetSessionInfoAndWindow(ani_env *env, const sptr &sessionInfo, + const sptr &uiWindow); + static void SetField(ani_env *env, ani_object object, ani_class cls, ani_field field, + const sptr &sessionInfo, const sptr &uiWindow); + static sptr GetSessionInfo(ani_env *env, ani_object object); + static sptr GetWindow(ani_env *env, ani_object object); + static ani_object CreateEtsSaveRequestCallback(ani_env *env, const sptr &sessionInfo, + const sptr &uiWindow); + static void SaveRequestSuccess(ani_env *env, ani_object object); + static void SaveRequestFailed(ani_env *env, ani_object object); + +private: + void OnSaveRequestSuccess(ani_env *env, ani_object object); + void OnSaveRequestFailed(ani_env *env, ani_object object); + void SendResultCodeAndViewData(ani_env *env, ani_object object, + const EtsAutoFillExtensionUtil::AutoFillResultCode &resultCode); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_SAVE_REQUEST_CALLBACK_H \ No newline at end of file -- Gitee