diff --git a/ability_runtime.gni b/ability_runtime.gni index 6d0eae9be2..42971ff590 100644 --- a/ability_runtime.gni +++ b/ability_runtime.gni @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2023 Huawei Device Co., Ltd. +# Copyright (c) 2021-2024 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 @@ -87,6 +87,8 @@ declare_args() { ability_runtime_feature_coverage = false ability_runtime_auto_fill_ability = "com.ohos.passwordbox/entry/AutoFillAbility" + ability_runtime_smart_auto_fill_ability = + "com.ohos.textautofill/entry/TextAutoFillAbility" if (!defined(global_parts_info) || defined(global_parts_info.account_os_account)) { diff --git a/frameworks/js/napi/auto_fill_extension_ability/auto_fill_extension_ability.js b/frameworks/js/napi/auto_fill_extension_ability/auto_fill_extension_ability.js index 6ee9d0e888..c9f22a1e6c 100644 --- a/frameworks/js/napi/auto_fill_extension_ability/auto_fill_extension_ability.js +++ b/frameworks/js/napi/auto_fill_extension_ability/auto_fill_extension_ability.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -28,6 +28,10 @@ class AutoFillExtensionAbility extends ExtensionAbility { console.log('onSaveRequest'); } + onUpdateRequest(request) { + console.log('onUpdateRequest'); + } + onSessionDestroy(session) { console.log('onSessionDestroy'); } diff --git a/frameworks/js/napi/auto_fill_manager/js_auto_fill_manager.cpp b/frameworks/js/napi/auto_fill_manager/js_auto_fill_manager.cpp index 74749d5d8b..8e8f8c979f 100644 --- a/frameworks/js/napi/auto_fill_manager/js_auto_fill_manager.cpp +++ b/frameworks/js/napi/auto_fill_manager/js_auto_fill_manager.cpp @@ -99,9 +99,10 @@ void JsAutoFillManager::OnRequestAutoSaveInner(napi_env env, int32_t instanceId, return; } if (uiContent->CheckNeedAutoSave()) { - AbilityBase::ViewData viewData; - uiContent->DumpViewData(viewData); - auto ret = AutoFillManager::GetInstance().RequestAutoSave(uiContent, viewData, saveRequestCallback); + AutoFill::AutoFillRequest request; + uiContent->DumpViewData(request.viewData, request.autoFillType); + request.autoFillCommand = AutoFill::AutoFillCommand::SAVE; + auto ret = AutoFillManager::GetInstance().RequestAutoSave(uiContent, request, saveRequestCallback); if (ret != ERR_OK) { HILOG_ERROR("Request auto save error[%{public}d].", ret); ThrowError(env, GetJsErrorCodeByNativeError(ret)); @@ -141,6 +142,44 @@ napi_value CreateJsAutoFillType(napi_env env) napi_set_named_property(env, objValue, "PASSWORD", CreateJsValue(env, AbilityBase::AutoFillType::PASSWORD)); napi_set_named_property(env, objValue, "USER_NAME", CreateJsValue(env, AbilityBase::AutoFillType::USER_NAME)); napi_set_named_property(env, objValue, "NEW_PASSWORD", CreateJsValue(env, AbilityBase::AutoFillType::NEW_PASSWORD)); + napi_set_named_property(env, objValue, "FULL_STREET_ADDRESS", + CreateJsValue(env, AbilityBase::AutoFillType::FULL_STREET_ADDRESS)); + napi_set_named_property(env, objValue, "HOUSE_NUMBER", CreateJsValue(env, AbilityBase::AutoFillType::HOUSE_NUMBER)); + napi_set_named_property(env, objValue, "DISTRICT_ADDRESS", + CreateJsValue(env, AbilityBase::AutoFillType::DISTRICT_ADDRESS)); + napi_set_named_property(env, objValue, "CITY_ADDRESS", CreateJsValue(env, AbilityBase::AutoFillType::CITY_ADDRESS)); + napi_set_named_property(env, objValue, "PROVINCE_ADDRESS", + CreateJsValue(env, AbilityBase::AutoFillType::PROVINCE_ADDRESS)); + napi_set_named_property(env, objValue, "COUNTRY_ADDRESS", + CreateJsValue(env, AbilityBase::AutoFillType::COUNTRY_ADDRESS)); + napi_set_named_property(env, objValue, "PERSON_FULL_NAME", + CreateJsValue(env, AbilityBase::AutoFillType::PERSON_FULL_NAME)); + napi_set_named_property(env, objValue, "PERSON_LAST_NAME", + CreateJsValue(env, AbilityBase::AutoFillType::PERSON_LAST_NAME)); + napi_set_named_property(env, objValue, "PERSON_FIRST_NAME", + CreateJsValue(env, AbilityBase::AutoFillType::PERSON_FIRST_NAME)); + napi_set_named_property(env, objValue, "PHONE_NUMBER", CreateJsValue(env, AbilityBase::AutoFillType::PHONE_NUMBER)); + napi_set_named_property(env, objValue, "PHONE_COUNTRY_CODE", + CreateJsValue(env, AbilityBase::AutoFillType::PHONE_COUNTRY_CODE)); + napi_set_named_property(env, objValue, "FULL_PHONE_NUMBER", + CreateJsValue(env, AbilityBase::AutoFillType::FULL_PHONE_NUMBER)); + napi_set_named_property(env, objValue, "EMAIL_ADDRESS", + CreateJsValue(env, AbilityBase::AutoFillType::EMAIL_ADDRESS)); + napi_set_named_property(env, objValue, "BANK_CARD_NUMBER", + CreateJsValue(env, AbilityBase::AutoFillType::BANK_CARD_NUMBER)); + napi_set_named_property(env, objValue, "ID_CARD_NUMBER", + CreateJsValue(env, AbilityBase::AutoFillType::ID_CARD_NUMBER)); + napi_set_named_property(env, objValue, "PRECISE_TIME", CreateJsValue(env, AbilityBase::AutoFillType::PRECISE_TIME)); + napi_set_named_property(env, objValue, "HOUR_AND_MINUTE", + CreateJsValue(env, AbilityBase::AutoFillType::HOUR_AND_MINUTE)); + napi_set_named_property(env, objValue, "DATE", CreateJsValue(env, AbilityBase::AutoFillType::DATE)); + napi_set_named_property(env, objValue, "MONTH", CreateJsValue(env, AbilityBase::AutoFillType::MONTH)); + napi_set_named_property(env, objValue, "YEAR", CreateJsValue(env, AbilityBase::AutoFillType::YEAR)); + napi_set_named_property(env, objValue, "NICKNAME", CreateJsValue(env, AbilityBase::AutoFillType::NICKNAME)); + napi_set_named_property(env, objValue, "DETAIL_INFO_WITHOUT_STREET", + CreateJsValue(env, AbilityBase::AutoFillType::DETAIL_INFO_WITHOUT_STREET)); + napi_set_named_property(env, objValue, "FORMAT_ADDRESS", + CreateJsValue(env, AbilityBase::AutoFillType::FORMAT_ADDRESS)); return objValue; } diff --git a/frameworks/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension.cpp b/frameworks/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension.cpp index 6c8a0d40ab..886ef9e3c8 100644 --- a/frameworks/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension.cpp +++ b/frameworks/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -48,8 +48,6 @@ namespace { constexpr size_t ARGC_ONE = 1; constexpr size_t ARGC_TWO = 2; constexpr size_t ARGC_THREE = 3; -constexpr const char *WANT_PARAMS_AUTO_FILL_CMD_AUTOSAVE = "save"; -constexpr const char *WANT_PARAMS_AUTO_FILL_CMD_AUTOFILL = "fill"; constexpr const char *WANT_PARAMS_AUTO_FILL_CMD = "ohos.ability.params.autoFillCmd"; constexpr static char WANT_PARAMS_AUTO_FILL_EVENT_KEY[] = "ability.want.params.AutoFillEvent"; } @@ -420,6 +418,20 @@ void JsAutoFillExtension::OnBackground() Extension::OnBackground(); } +void JsAutoFillExtension::UpdateRequest(const AAFwk::WantParams &wantParams) +{ + HILOG_DEBUG("Called."); + HandleScope handleScope(jsRuntime_); + napi_env env = jsRuntime_.GetNapiEnv(); + napi_value request = JsAutoFillExtensionUtil::WrapUpdateRequest(wantParams, env); + if (request == nullptr) { + HILOG_ERROR("Failed to create update request."); + return; + } + napi_value argv[] = { request }; + CallObjectMethod("onUpdateRequest", argv, ARGC_ONE); +} + bool JsAutoFillExtension::HandleAutoFillCreate(const AAFwk::Want &want, const sptr &sessionInfo) { HILOG_DEBUG("Called."); @@ -477,6 +489,7 @@ void JsAutoFillExtension::ForegroundWindow(const AAFwk::Want &want, const sptr(JsAutoFillExtensionUtil::AutoFillResultCode::CALLBACK_REMOVE_TIME_OUT))); @@ -588,23 +601,25 @@ void JsAutoFillExtension::CallJsOnRequest( contentSessions_.emplace( sessionInfo->sessionToken, std::shared_ptr(reinterpret_cast(ref))); - napi_value fillrequest = JsAutoFillExtensionUtil::WrapFillRequest(want, env); - if (fillrequest == nullptr) { + napi_value request = JsAutoFillExtensionUtil::WrapFillRequest(want, env); + if (request == nullptr) { HILOG_ERROR("Fill request is nullptr."); + return; } napi_value callback = nullptr; - auto cmdValue = want.GetStringParam(WANT_PARAMS_AUTO_FILL_CMD); - if (cmdValue == WANT_PARAMS_AUTO_FILL_CMD_AUTOSAVE) { + auto cmdValue = want.GetIntParam(WANT_PARAMS_AUTO_FILL_CMD, 0); + if (cmdValue == AutoFillCommand::SAVE) { callback = JsSaveRequestCallback::CreateJsSaveRequestCallback(env, sessionInfo, uiWindow); - napi_value argv[] = { nativeContentSession, fillrequest, callback }; + napi_value argv[] = { nativeContentSession, request, callback }; CallObjectMethod("onSaveRequest", argv, ARGC_THREE); - } else if (cmdValue == WANT_PARAMS_AUTO_FILL_CMD_AUTOFILL) { + } else if (cmdValue == AutoFillCommand::FILL) { callback = JsFillRequestCallback::CreateJsFillRequestCallback(env, sessionInfo, uiWindow); - napi_value argv[] = { nativeContentSession, fillrequest, callback }; + napi_value argv[] = { nativeContentSession, request, callback }; CallObjectMethod("onFillRequest", argv, ARGC_THREE); } else { - HILOG_DEBUG("Invalid auto fill request type."); + HILOG_ERROR("Invalid auto fill request type."); + return; } napi_ref callbackRef = nullptr; @@ -612,5 +627,26 @@ void JsAutoFillExtension::CallJsOnRequest( callbacks_.emplace(sessionInfo->sessionToken, std::shared_ptr(reinterpret_cast(callbackRef))); } + +void JsAutoFillExtension::RegisterTransferComponentDataListener(const sptr &uiWindow) +{ + HILOG_DEBUG("Called."); + if (uiWindow == nullptr) { + HILOG_ERROR("Invalid ui window object."); + return; + } + + auto handler = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); + if (handler == nullptr) { + HILOG_ERROR("Failed to create event handler."); + return; + } + uiWindow->RegisterTransferComponentDataListener([this, handler]( + const AAFwk::WantParams &wantParams) { + handler->PostTask([this, wantParams]() { + JsAutoFillExtension::UpdateRequest(wantParams); + }, "JsAutoFillExtension:UpdateRequest"); + }); +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension_util.cpp b/frameworks/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension_util.cpp index d92c96bea5..3c996bd4f4 100644 --- a/frameworks/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension_util.cpp +++ b/frameworks/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension_util.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -28,6 +28,7 @@ constexpr const char *VIEW_DATA_PAGEURL = "pageUrl"; constexpr const char *VIEW_DATA_PAGE_NODE_INFOS = "pageNodeInfos"; constexpr const char *VIEW_DATA_VIEW_DATA = "viewData"; constexpr const char *VIEW_DATA_TYPE = "type"; +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"; @@ -36,8 +37,16 @@ constexpr const char *PAGE_INFO_VALUE = "value"; constexpr const char *PAGE_INFO_PLACEHOLDER = "placeholder"; 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 *WANT_PARAMS_VIEW_DATA = "ohos.ability.params.viewData"; constexpr const char *WANT_PARAMS_AUTO_FILL_TYPE_KEY = "ability.want.params.AutoFillType"; +constexpr const char *WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY = "ohos.ability.params.popupWindow"; +constexpr const char *WANT_PARAMS_IS_POPUP = "isPopup"; +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 @@ -72,6 +81,9 @@ napi_value JsAutoFillExtensionUtil::WrapViewData(const napi_env env, const Abili } } + jsValue = WrapRectData(env, viewData.pageRect); + SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_PAGE_RECT, jsValue); + SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_PAGE_NODE_INFOS, jsArray); return jsObject; } @@ -106,6 +118,33 @@ napi_value JsAutoFillExtensionUtil::WrapPageNodeInfo(const napi_env env, const A jsValue = WrapBoolToJS(env, pageNodeInfo.enableAutoFill); SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_ENABLEAUTOFILL, jsValue); + jsValue = WrapRectData(env, pageNodeInfo.rect); + SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_PAGE_NODE_RECT, jsValue); + + jsValue = WrapBoolToJS(env, pageNodeInfo.isFocus); + SetPropertyValueByPropertyName(env, jsObject, PAGE_INFO_IS_FOCUS, jsValue); + + return jsObject; +} + +napi_value JsAutoFillExtensionUtil::WrapRectData(const napi_env env, const AbilityBase::Rect &rect) +{ + HILOG_DEBUG("Called."); + napi_value jsObject = nullptr; + NAPI_CALL(env, napi_create_object(env, &jsObject)); + napi_value jsValue = nullptr; + jsValue = AppExecFwk::WrapDoubleToJS(env, rect.left); + SetPropertyValueByPropertyName(env, jsObject, RECT_POSITION_LEFT, jsValue); + + jsValue = AppExecFwk::WrapDoubleToJS(env, rect.top); + SetPropertyValueByPropertyName(env, jsObject, RECT_POSITION_TOP, jsValue); + + jsValue = AppExecFwk::WrapDoubleToJS(env, rect.width); + SetPropertyValueByPropertyName(env, jsObject, RECT_WIDTH, jsValue); + + jsValue = AppExecFwk::WrapDoubleToJS(env, rect.height); + SetPropertyValueByPropertyName(env, jsObject, RECT_HEIGHT, jsValue); + return jsObject; } @@ -144,6 +183,8 @@ void JsAutoFillExtensionUtil::UnwrapViewData( viewData.nodes.emplace_back(node); } } + jsValue = GetPropertyValueByPropertyName(env, jsViewData, VIEW_DATA_PAGE_RECT, napi_object); + UnwrapRectData(env, jsValue, viewData.pageRect); } void JsAutoFillExtensionUtil::UnwrapPageNodeInfo( @@ -160,6 +201,27 @@ void JsAutoFillExtensionUtil::UnwrapPageNodeInfo( UnwrapStringByPropertyName(env, jsNode, PAGE_INFO_PASSWORDRULES, node.passwordRules); UnwrapStringByPropertyName(env, jsNode, PAGE_INFO_PLACEHOLDER, node.placeholder); UnwrapBooleanByPropertyName(env, jsNode, PAGE_INFO_ENABLEAUTOFILL, node.enableAutoFill); + auto jsValue = GetPropertyValueByPropertyName(env, jsNode, PAGE_INFO_PAGE_NODE_RECT, napi_object); + UnwrapRectData(env, jsValue, node.rect); + UnwrapBooleanByPropertyName(env, jsNode, PAGE_INFO_IS_FOCUS, node.isFocus); +} + +void JsAutoFillExtensionUtil::UnwrapRectData( + const napi_env env, const napi_value value, AbilityBase::Rect &rect) +{ + HILOG_DEBUG("Called."); + int32_t position; + UnwrapInt32ByPropertyName(env, value, RECT_POSITION_LEFT, position); + rect.left = position; + + UnwrapInt32ByPropertyName(env, value, RECT_POSITION_TOP, position); + rect.top = position; + + UnwrapInt32ByPropertyName(env, value, RECT_WIDTH, position); + rect.width = position; + + UnwrapInt32ByPropertyName(env, value, RECT_HEIGHT, position); + rect.height = position; } napi_value JsAutoFillExtensionUtil::WrapFillRequest(const AAFwk::Want &want, const napi_env env) @@ -192,6 +254,36 @@ napi_value JsAutoFillExtensionUtil::WrapFillRequest(const AAFwk::Want &want, con napi_value viewDataValue = WrapViewData(env, viewData); SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_VIEW_DATA, viewDataValue); } + + if (want.HasParameter(WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY)) { + auto isPopup = want.GetBoolParam(WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY, false); + + napi_value jsValue = AppExecFwk::WrapBoolToJS(env, isPopup); + SetPropertyValueByPropertyName(env, jsObject, WANT_PARAMS_IS_POPUP, jsValue); + } + return jsObject; +} + +napi_value JsAutoFillExtensionUtil::WrapUpdateRequest(const AAFwk::WantParams &wantParams, const napi_env env) +{ + HILOG_DEBUG("Called."); + napi_value jsObject = nullptr; + NAPI_CALL(env, napi_create_object(env, &jsObject)); + if (jsObject == nullptr) { + HILOG_ERROR("Failed to create Object."); + return nullptr; + } + + std::string viewDataString = wantParams.GetStringParam(WANT_PARAMS_VIEW_DATA); + if (viewDataString.empty()) { + HILOG_ERROR("View data is empty."); + return jsObject; + } + + AbilityBase::ViewData viewData; + viewData.FromJsonString(viewDataString); + napi_value viewDataValue = WrapViewData(env, viewData); + SetPropertyValueByPropertyName(env, jsObject, VIEW_DATA_VIEW_DATA, viewDataValue); return jsObject; } diff --git a/frameworks/native/ability/native/extension_ability_thread.cpp b/frameworks/native/ability/native/extension_ability_thread.cpp index 7efc0263a7..bb30d5d0fd 100644 --- a/frameworks/native/ability/native/extension_ability_thread.cpp +++ b/frameworks/native/ability/native/extension_ability_thread.cpp @@ -56,6 +56,7 @@ const std::map UI_EXTENSION_NAME_ { AppExecFwk::ExtensionAbilityType::SHARE, SHARE_EXTENSION }, { AppExecFwk::ExtensionAbilityType::ACTION, ACTION_EXTENSION }, { AppExecFwk::ExtensionAbilityType::AUTO_FILL_PASSWORD, AUTO_FILL_EXTENSION }, + { AppExecFwk::ExtensionAbilityType::AUTO_FILL_SMART, AUTO_FILL_EXTENSION }, { AppExecFwk::ExtensionAbilityType::EMBEDDED_UI, EMBEDDED_UI_EXTENSION } }; diff --git a/interfaces/inner_api/auto_fill_manager/BUILD.gn b/interfaces/inner_api/auto_fill_manager/BUILD.gn index f9eddb2152..5d5f6fa97c 100644 --- a/interfaces/inner_api/auto_fill_manager/BUILD.gn +++ b/interfaces/inner_api/auto_fill_manager/BUILD.gn @@ -34,6 +34,7 @@ ohos_shared_library("auto_fill_manager") { "src/auto_fill_event_handler.cpp", "src/auto_fill_extension_callback.cpp", "src/auto_fill_manager.cpp", + "src/auto_fill_manager_util.cpp", ] deps = [ diff --git a/interfaces/inner_api/auto_fill_manager/include/auto_fill_custom_config.h b/interfaces/inner_api/auto_fill_manager/include/auto_fill_custom_config.h new file mode 100644 index 0000000000..c27e33c2dd --- /dev/null +++ b/interfaces/inner_api/auto_fill_manager/include/auto_fill_custom_config.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024 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_AUTO_FILL_CUSTOM_CONFIG_H +#define OHOS_ABILITY_RUNTIME_AUTO_FILL_CUSTOM_CONFIG_H + +#include +#include + +namespace OHOS { +namespace AbilityRuntime { +namespace AutoFill { +enum class PopupPlacement { + LEFT, + RIGHT, + TOP, + BOTTOM, + TOP_LEFT, + TOP_RIGHT, + BOTTOM_LEFT, + BOTTOM_RIGHT, + LEFT_TOP, + LEFT_BOTTOM, + RIGHT_TOP, + RIGHT_BOTTOM, + NONE, +}; + +enum class PopupDimensionUnit { + PX = 0, + VP, + FP, + PERCENT, + LPX, + AUTO, + CALC, +}; + +struct PopupOffset { + PopupDimensionUnit unit = PopupDimensionUnit::PX; + double deltaX = 0.0; + double deltaY = 0.0; +}; + +struct PopupSize { + PopupDimensionUnit unit = PopupDimensionUnit::PX; + double width = 0.0; + double height = 0.0; +}; + +struct PopupLength { + PopupDimensionUnit unit = PopupDimensionUnit::PX; + double length = 0.0; +}; + +struct AutoFillCustomConfig { + bool isShowInSubWindow = true; + std::string inspectorId; + std::int32_t nodeId = -1; + std::optional isAutoCancel; + std::optional isEnableArrow; + std::optional targetSize; + std::optional targetOffset; + std::optional targetSpace; + std::optional arrowOffset; + std::optional placement; + std::optional backgroundColor; + std::optional maskColor; + std::function onStateChange; +}; +} // AutoFill +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_AUTO_FILL_CUSTOM_CONFIG_H \ No newline at end of file diff --git a/interfaces/inner_api/auto_fill_manager/include/auto_fill_error.h b/interfaces/inner_api/auto_fill_manager/include/auto_fill_error.h index d23421cf5d..7cc4d9a31b 100644 --- a/interfaces/inner_api/auto_fill_manager/include/auto_fill_error.h +++ b/interfaces/inner_api/auto_fill_manager/include/auto_fill_error.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -29,6 +29,7 @@ enum { AUTO_FILL_OBJECT_IS_NULL, AUTO_FILL_CREATE_MODULE_UI_EXTENSION_FAILED, AUTO_FILL_REQUEST_TIME_OUT, + AUTO_FILL_TYPE_INVALID }; } // namespace AutoFill } // namespace AbilityRuntime diff --git a/interfaces/inner_api/auto_fill_manager/include/auto_fill_extension_callback.h b/interfaces/inner_api/auto_fill_manager/include/auto_fill_extension_callback.h index 30608df5a3..3a29f8ebd5 100644 --- a/interfaces/inner_api/auto_fill_manager/include/auto_fill_extension_callback.h +++ b/interfaces/inner_api/auto_fill_manager/include/auto_fill_extension_callback.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -23,6 +23,12 @@ namespace OHOS { namespace AbilityRuntime { +namespace AutoFill { +enum AutoFillWindowType { + MODAL_WINDOW, + POPUP_WINDOW +}; +} class AutoFillExtensionCallback { public: AutoFillExtensionCallback() = default; @@ -32,6 +38,8 @@ public: void OnRelease(int32_t errCode); void OnError(int32_t errCode, const std::string &name, const std::string &message); void OnReceive(const AAFwk::WantParams &wantParams); + void onRemoteReady(const std::shared_ptr &modalUIExtensionProxy); + void onDestroy(); void SetFillRequestCallback(const std::shared_ptr &callback); void SetSaveRequestCallback(const std::shared_ptr &callback); @@ -39,6 +47,7 @@ public: void SetSessionId(int32_t sessionId); void SetUIContent(Ace::UIContent *uiContent); void SetEventId(uint32_t eventId); + void SetWindowType(const AutoFill::AutoFillWindowType &autoFillWindowType); void HandleTimeOut(); private: @@ -51,6 +60,7 @@ private: int32_t sessionId_; Ace::UIContent *uiContent_ = nullptr; uint32_t eventId_ = 0; + AutoFill::AutoFillWindowType autoFillWindowType_ = AutoFill::AutoFillWindowType::MODAL_WINDOW; }; } // AbilityRuntime } // OHOS diff --git a/interfaces/inner_api/auto_fill_manager/include/auto_fill_manager.h b/interfaces/inner_api/auto_fill_manager/include/auto_fill_manager.h index f9fb4660f5..f3fb362ea9 100644 --- a/interfaces/inner_api/auto_fill_manager/include/auto_fill_manager.h +++ b/interfaces/inner_api/auto_fill_manager/include/auto_fill_manager.h @@ -18,6 +18,7 @@ #include +#include "auto_fill_custom_config.h" #include "auto_fill_event_handler.h" #include "auto_fill_extension_callback.h" #include "fill_request_callback_interface.h" @@ -28,6 +29,28 @@ namespace OHOS { namespace AbilityRuntime { +namespace AutoFill { +enum class AutoFillCommand { + NONE, + FILL, + SAVE, + UPDATE, + RESIZE, + INPUT, + RELOAD_IN_MODAL +}; + +/** + * @struct AutoFillRequest + * AutoFillRequest is used to define the auto fill request parameter structure. + */ +struct AutoFillRequest { + AbilityBase::AutoFillType autoFillType = AbilityBase::AutoFillType::UNSPECIFIED; + AutoFillCommand autoFillCommand = AutoFillCommand::NONE; + AbilityBase::ViewData viewData; + AutoFillCustomConfig config; +}; +} class AutoFillManager { public: AutoFillManager() = default; @@ -36,29 +59,40 @@ public: static AutoFillManager &GetInstance(); int32_t RequestAutoFill( - const AbilityBase::AutoFillType &autoFillType, Ace::UIContent *uiContent, - const AbilityBase::ViewData &viewdata, - const std::shared_ptr &fillCallback); + const AutoFill::AutoFillRequest &request, + const std::shared_ptr &fillCallback, bool &isPopup); int32_t RequestAutoSave( Ace::UIContent *uiContent, - const AbilityBase::ViewData &viewdata, + const AutoFill::AutoFillRequest &request, const std::shared_ptr &saveCallback); + void UpdateCustomPopupUIExtension(Ace::UIContent *uiContent, const AbilityBase::ViewData &viewData); + void SetAutoFillExtensionProxy(Ace::UIContent *uiContent, + const std::shared_ptr &modalUIExtensionProxy); + void RemoveAutoFillExtensionProxy(Ace::UIContent *uiContent); void HandleTimeOut(uint32_t eventId); void RemoveEvent(uint32_t eventId); private: - void SetTimeOutEvent(uint32_t eventId); int32_t HandleRequestExecuteInner( - const AbilityBase::AutoFillType &autoFillType, Ace::UIContent *uiContent, - const AbilityBase::ViewData &viewdata, + const AutoFill::AutoFillRequest &request, const std::shared_ptr &fillCallback, - const std::shared_ptr &saveCallback); + const std::shared_ptr &saveCallback, bool &isPopup); + int32_t CreateAutoFillExtension(Ace::UIContent *uiContent, + const AutoFill::AutoFillRequest &request, + const Ace::ModalUIExtensionCallbacks &callback, + const AutoFill::AutoFillWindowType autoFillWindowType, + bool isSmartAutoFill); + void SetTimeOutEvent(uint32_t eventId); + AutoFill::AutoFillWindowType ConvertAutoFillWindowType(const AutoFill::AutoFillRequest &request, + bool &isSmartAutoFill); - std::mutex mutexLock_; + std::mutex extensionCallbacksMutex_; + std::mutex modalProxyMapMutex_; std::map> extensionCallbacks_; + std::map> modalUIExtensionProxyMap_; uint32_t eventId_ = 0; std::shared_ptr eventHandler_; }; diff --git a/interfaces/inner_api/auto_fill_manager/include/auto_fill_manager_util.h b/interfaces/inner_api/auto_fill_manager/include/auto_fill_manager_util.h new file mode 100644 index 0000000000..75bba9f77a --- /dev/null +++ b/interfaces/inner_api/auto_fill_manager/include/auto_fill_manager_util.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 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_AUTO_FILL_MANAGER_UTIL_H +#define OHOS_ABILITY_RUNTIME_AUTO_FILL_MANAGER_UTIL_H + +#include "auto_fill_custom_config.h" +#include "popup_ui_extension_config.h" + +namespace OHOS { +namespace AbilityRuntime { +class AutoFillManagerUtil { +public: + AutoFillManagerUtil() = default; + ~AutoFillManagerUtil() = default; + + static void ConvertToPopupUIExtensionConfig(const AutoFill::AutoFillCustomConfig &config, + Ace::CustomPopupUIExtensionConfig &popupConfig); + static Ace::PopupDimensionUnit ConvertPopupUnit(const AutoFill::PopupDimensionUnit &unit); + static Ace::PopupPlacement ConvertPopupPlacement(const AutoFill::PopupPlacement &placement); +}; +} // AbilityRuntime +} // OHOS +#endif // OHOS_ABILITY_RUNTIME_AUTO_FILL_MANAGER_UTIL_H \ No newline at end of file diff --git a/interfaces/inner_api/auto_fill_manager/src/auto_fill_extension_callback.cpp b/interfaces/inner_api/auto_fill_manager/src/auto_fill_extension_callback.cpp index 3bdd47ce33..ca8e25212f 100644 --- a/interfaces/inner_api/auto_fill_manager/src/auto_fill_extension_callback.cpp +++ b/interfaces/inner_api/auto_fill_manager/src/auto_fill_extension_callback.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -73,6 +73,27 @@ void AutoFillExtensionCallback::OnReceive(const AAFwk::WantParams &wantParams) AutoFillManager::GetInstance().RemoveEvent(eventId_); } +void AutoFillExtensionCallback::onRemoteReady(const std::shared_ptr &modalUIExtensionProxy) +{ + HILOG_DEBUG("Called."); + if (modalUIExtensionProxy == nullptr || uiContent_ == nullptr) { + HILOG_ERROR("Proxy or uiContent_ is nullptr."); + return; + } + AutoFillManager::GetInstance().SetAutoFillExtensionProxy(uiContent_, modalUIExtensionProxy); +} + +void AutoFillExtensionCallback::onDestroy() +{ + HILOG_DEBUG("Called."); + AutoFillManager::GetInstance().RemoveEvent(eventId_); + if (uiContent_ != nullptr && autoFillWindowType_ == AutoFill::AutoFillWindowType::POPUP_WINDOW) { + AutoFillManager::GetInstance().RemoveAutoFillExtensionProxy(uiContent_); + } + uiContent_ = nullptr; + SendAutoFillFailed(AutoFill::AUTO_FILL_CANCEL); +} + void AutoFillExtensionCallback::SetFillRequestCallback(const std::shared_ptr &callback) { fillCallback_ = callback; @@ -98,6 +119,11 @@ void AutoFillExtensionCallback::SetEventId(uint32_t eventId) eventId_ = eventId; } +void AutoFillExtensionCallback::SetWindowType(const AutoFill::AutoFillWindowType &autoFillWindowType) +{ + autoFillWindowType_ = autoFillWindowType; +} + void AutoFillExtensionCallback::HandleTimeOut() { CloseModalUIExtension(); @@ -111,10 +137,12 @@ void AutoFillExtensionCallback::SendAutoFillSucess(const AAFwk::Want &want) AbilityBase::ViewData viewData; viewData.FromJsonString(dataStr.c_str()); fillCallback_->OnFillRequestSuccess(viewData); + fillCallback_ = nullptr; } if (saveCallback_ != nullptr) { saveCallback_->OnSaveRequestSuccess(); + saveCallback_ = nullptr; } } @@ -122,10 +150,12 @@ void AutoFillExtensionCallback::SendAutoFillFailed(int32_t errCode) { if (fillCallback_ != nullptr) { fillCallback_->OnFillRequestFailed(errCode); + fillCallback_ = nullptr; } if (saveCallback_ != nullptr) { saveCallback_->OnSaveRequestFailed(); + saveCallback_ = nullptr; } } @@ -135,7 +165,13 @@ void AutoFillExtensionCallback::CloseModalUIExtension() HILOG_DEBUG("uiContent_ is nullptr."); return; } - uiContent_->CloseModalUIExtension(sessionId_); + + if (autoFillWindowType_ == AutoFill::AutoFillWindowType::POPUP_WINDOW) { + AutoFillManager::GetInstance().RemoveAutoFillExtensionProxy(uiContent_); + uiContent_->DestroyCustomPopupUIExtension(sessionId_); + } else if (autoFillWindowType_ == AutoFill::AutoFillWindowType::MODAL_WINDOW) { + uiContent_->CloseModalUIExtension(sessionId_); + } uiContent_ = nullptr; } } // namespace AbilityRuntime diff --git a/interfaces/inner_api/auto_fill_manager/src/auto_fill_manager.cpp b/interfaces/inner_api/auto_fill_manager/src/auto_fill_manager.cpp index bd3044cabd..bae1773cd2 100644 --- a/interfaces/inner_api/auto_fill_manager/src/auto_fill_manager.cpp +++ b/interfaces/inner_api/auto_fill_manager/src/auto_fill_manager.cpp @@ -16,21 +16,26 @@ #include "auto_fill_manager.h" #include "auto_fill_error.h" +#include "auto_fill_manager_util.h" #include "extension_ability_info.h" #include "hilog_wrapper.h" +#include "int_wrapper.h" +#include "parameters.h" +#include "string_wrapper.h" namespace OHOS { namespace AbilityRuntime { namespace { -const std::string WANT_PARAMS_AUTO_FILL_CMD = "fill"; -const std::string WANT_PARAMS_AUTO_SAVE_CMD = "save"; const std::string WANT_PARAMS_EXTENSION_TYPE = "autoFill/password"; +const std::string WANT_PARAMS_SMART_EXTENSION_TYPE = "autoFill/smart"; constexpr static char WANT_PARAMS_VIEW_DATA_KEY[] = "ohos.ability.params.viewData"; constexpr static char WANT_PARAMS_AUTO_FILL_CMD_KEY[] = "ohos.ability.params.autoFillCmd"; +constexpr static char WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY[] = "ohos.ability.params.popupWindow"; constexpr static char WANT_PARAMS_EXTENSION_TYPE_KEY[] = "ability.want.params.uiExtensionType"; constexpr static char WANT_PARAMS_AUTO_FILL_TYPE_KEY[] = "ability.want.params.AutoFillType"; constexpr static char AUTO_FILL_MANAGER_THREAD[] = "AutoFillManager"; constexpr static uint32_t AUTO_FILL_REQUEST_TIME_OUT_VALUE = 1000; +constexpr static uint32_t AUTO_FILL_UI_EXTENSION_SESSION_ID_INVALID = 0; } // namespace AutoFillManager &AutoFillManager::GetInstance() { @@ -47,62 +52,58 @@ AutoFillManager::~AutoFillManager() } int32_t AutoFillManager::RequestAutoFill( - const AbilityBase::AutoFillType &autoFillType, Ace::UIContent *uiContent, - const AbilityBase::ViewData &viewdata, - const std::shared_ptr &fillCallback) + const AutoFill::AutoFillRequest &request, + const std::shared_ptr &fillCallback, bool &isPopup) { HILOG_DEBUG("Called."); if (uiContent == nullptr || fillCallback == nullptr) { HILOG_ERROR("UIContent or fillCallback is nullptr."); return AutoFill::AUTO_FILL_OBJECT_IS_NULL; } - return HandleRequestExecuteInner(autoFillType, uiContent, viewdata, fillCallback, nullptr); + + if (request.autoFillType == AbilityBase::AutoFillType::UNSPECIFIED) { + HILOG_ERROR("Auto fill type is invalid."); + return AutoFill::AUTO_FILL_TYPE_INVALID; + } + return HandleRequestExecuteInner(uiContent, request, fillCallback, nullptr, isPopup); } int32_t AutoFillManager::RequestAutoSave( Ace::UIContent *uiContent, - const AbilityBase::ViewData &viewdata, + const AutoFill::AutoFillRequest &request, const std::shared_ptr &saveCallback) { HILOG_DEBUG("Called."); if (uiContent == nullptr || saveCallback == nullptr) { - HILOG_ERROR("UIContent or save callback is nullptr."); + HILOG_ERROR("UIContent or saveCallback is nullptr."); return AutoFill::AUTO_FILL_OBJECT_IS_NULL; } - return HandleRequestExecuteInner( - AbilityBase::AutoFillType::UNSPECIFIED, uiContent, viewdata, nullptr, saveCallback); + bool isPopup = false; + return HandleRequestExecuteInner(uiContent, request, nullptr, saveCallback, isPopup); } int32_t AutoFillManager::HandleRequestExecuteInner( - const AbilityBase::AutoFillType &autoFillType, Ace::UIContent *uiContent, - const AbilityBase::ViewData &viewdata, + const AutoFill::AutoFillRequest &request, const std::shared_ptr &fillCallback, - const std::shared_ptr &saveCallback) + const std::shared_ptr &saveCallback, bool &isPopup) { if (uiContent == nullptr || (fillCallback == nullptr && saveCallback == nullptr)) { HILOG_ERROR("UIContent or fillCallback&saveCallback is nullptr."); return AutoFill::AUTO_FILL_OBJECT_IS_NULL; } { - std::lock_guard lock(mutexLock_); + std::lock_guard lock(extensionCallbacksMutex_); SetTimeOutEvent(++eventId_); } - AAFwk::Want want; - want.SetParam(WANT_PARAMS_EXTENSION_TYPE_KEY, WANT_PARAMS_EXTENSION_TYPE); - want.SetParam(WANT_PARAMS_VIEW_DATA_KEY, viewdata.ToJsonString()); auto extensionCallback = std::make_shared(); if (fillCallback != nullptr) { - want.SetParam(WANT_PARAMS_AUTO_FILL_CMD_KEY, WANT_PARAMS_AUTO_FILL_CMD); - want.SetParam(WANT_PARAMS_AUTO_FILL_TYPE_KEY, static_cast(autoFillType)); extensionCallback->SetFillRequestCallback(fillCallback); } else { - want.SetParam(WANT_PARAMS_AUTO_FILL_CMD_KEY, WANT_PARAMS_AUTO_SAVE_CMD); extensionCallback->SetSaveRequestCallback(saveCallback); } - Ace::ModalUIExtensionCallbacks callback; callback.onResult = std::bind( &AutoFillExtensionCallback::OnResult, extensionCallback, std::placeholders::_1, std::placeholders::_2); @@ -111,22 +112,141 @@ int32_t AutoFillManager::HandleRequestExecuteInner( callback.onError = std::bind(&AutoFillExtensionCallback::OnError, extensionCallback, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); callback.onReceive = std::bind(&AutoFillExtensionCallback::OnReceive, extensionCallback, std::placeholders::_1); - Ace::ModalUIExtensionConfig config; - config.isAsyncModalBinding = true; - int32_t sessionId = uiContent->CreateModalUIExtension(want, callback, config); - if (sessionId == 0) { - HILOG_ERROR("Create modal ui extension is failed."); + callback.onRemoteReady = std::bind(&AutoFillExtensionCallback::onRemoteReady, + extensionCallback, std::placeholders::_1); + callback.onDestroy = std::bind(&AutoFillExtensionCallback::onDestroy, extensionCallback); + + bool isSmartAutoFill = false; + auto autoFillWindowType = ConvertAutoFillWindowType(request, isSmartAutoFill); + isPopup = autoFillWindowType == AutoFill::AutoFillWindowType::POPUP_WINDOW ? true : false; + auto sessionId = CreateAutoFillExtension(uiContent, request, callback, autoFillWindowType, isSmartAutoFill); + if (sessionId == AUTO_FILL_UI_EXTENSION_SESSION_ID_INVALID) { + HILOG_ERROR("Create ui extension is failed."); RemoveEvent(eventId_); return AutoFill::AUTO_FILL_CREATE_MODULE_UI_EXTENSION_FAILED; } extensionCallback->SetUIContent(uiContent); extensionCallback->SetSessionId(sessionId); extensionCallback->SetEventId(eventId_); - std::lock_guard lock(mutexLock_); + extensionCallback->SetWindowType(autoFillWindowType); + std::lock_guard lock(extensionCallbacksMutex_); extensionCallbacks_.emplace(eventId_, extensionCallback); return AutoFill::AUTO_FILL_SUCCESS; } +void AutoFillManager::UpdateCustomPopupUIExtension(Ace::UIContent *uiContent, const AbilityBase::ViewData &viewData) +{ + HILOG_DEBUG("Called."); + if (uiContent == nullptr) { + HILOG_ERROR("UIContent is nullptr."); + return; + } + + std::shared_ptr modalUIExtensionProxy; + { + std::lock_guard lock(modalProxyMapMutex_); + auto it = modalUIExtensionProxyMap_.find(uiContent); + if (it == modalUIExtensionProxyMap_.end()) { + HILOG_ERROR("Content is not in map."); + return; + } + modalUIExtensionProxy = it->second; + } + + if (modalUIExtensionProxy != nullptr) { + AAFwk::WantParams wantParams; + wantParams.SetParam(WANT_PARAMS_AUTO_FILL_CMD_KEY, + AAFwk::Integer::Box(static_cast(AutoFill::AutoFillCommand::UPDATE))); + wantParams.SetParam(WANT_PARAMS_VIEW_DATA_KEY, AAFwk::String::Box(viewData.ToJsonString())); + modalUIExtensionProxy->SendData(wantParams); + } +} + +void AutoFillManager::SetAutoFillExtensionProxy(Ace::UIContent *uiContent, + const std::shared_ptr &modalUIExtensionProxy) +{ + HILOG_DEBUG("Called."); + if (uiContent == nullptr || modalUIExtensionProxy == nullptr) { + HILOG_ERROR("UIContent or proxy is nullptr."); + return; + } + + std::lock_guard lock(modalProxyMapMutex_); + auto it = modalUIExtensionProxyMap_.find(uiContent); + if (it != modalUIExtensionProxyMap_.end()) { + modalUIExtensionProxyMap_.erase(it); + } + modalUIExtensionProxyMap_.emplace(uiContent, modalUIExtensionProxy); +} + +void AutoFillManager::RemoveAutoFillExtensionProxy(Ace::UIContent *uiContent) +{ + HILOG_DEBUG("Called."); + if (uiContent == nullptr) { + HILOG_ERROR("Content is nullptr."); + return; + } + std::lock_guard lock(modalProxyMapMutex_); + auto it = modalUIExtensionProxyMap_.find(uiContent); + if (it != modalUIExtensionProxyMap_.end()) { + modalUIExtensionProxyMap_.erase(it); + } +} + +int32_t AutoFillManager::CreateAutoFillExtension(Ace::UIContent *uiContent, + const AutoFill::AutoFillRequest &request, + const Ace::ModalUIExtensionCallbacks &callback, + const AutoFill::AutoFillWindowType autoFillWindowType, + bool isSmartAutoFill) +{ + int32_t sessionId = AUTO_FILL_UI_EXTENSION_SESSION_ID_INVALID; + if (uiContent == nullptr) { + HILOG_ERROR("Content is nullptr."); + return sessionId; + } + + AAFwk::Want want; + want.SetParam(WANT_PARAMS_AUTO_FILL_CMD_KEY, static_cast(request.autoFillCommand)); + want.SetParam(WANT_PARAMS_AUTO_FILL_TYPE_KEY, static_cast(request.autoFillType)); + want.SetParam(WANT_PARAMS_VIEW_DATA_KEY, request.viewData.ToJsonString()); + isSmartAutoFill ? want.SetParam(WANT_PARAMS_EXTENSION_TYPE_KEY, WANT_PARAMS_SMART_EXTENSION_TYPE) : + want.SetParam(WANT_PARAMS_EXTENSION_TYPE_KEY, WANT_PARAMS_EXTENSION_TYPE); + + if (autoFillWindowType == AutoFill::AutoFillWindowType::POPUP_WINDOW) { + want.SetParam(WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY, true); + Ace::CustomPopupUIExtensionConfig popupConfig; + AutoFillManagerUtil::ConvertToPopupUIExtensionConfig(request.config, popupConfig); + sessionId = uiContent->CreateCustomPopupUIExtension(want, callback, popupConfig); + } else if (autoFillWindowType == AutoFill::AutoFillWindowType::MODAL_WINDOW) { + want.SetParam(WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY, false); + Ace::ModalUIExtensionConfig config; + config.isAsyncModalBinding = true; + sessionId = uiContent->CreateModalUIExtension(want, callback, config); + } + return sessionId; +} + +AutoFill::AutoFillWindowType AutoFillManager::ConvertAutoFillWindowType(const AutoFill::AutoFillRequest &request, + bool &isSmartAutoFill) +{ + AutoFill::AutoFillWindowType autoFillWindowType = AutoFill::AutoFillWindowType::MODAL_WINDOW; + AbilityBase::AutoFillType autoFillType = request.autoFillType; + if (autoFillType >= AbilityBase::AutoFillType::FULL_STREET_ADDRESS && + autoFillType <= AbilityBase::AutoFillType::FORMAT_ADDRESS) { + autoFillWindowType = AutoFill::AutoFillWindowType::POPUP_WINDOW; + isSmartAutoFill = true; + } else if (autoFillType == AbilityBase::AutoFillType::PASSWORD || + autoFillType == AbilityBase::AutoFillType::USER_NAME || + autoFillType == AbilityBase::AutoFillType::NEW_PASSWORD) { + autoFillWindowType = AutoFill::AutoFillWindowType::MODAL_WINDOW; + isSmartAutoFill = false; + } + + autoFillWindowType = request.autoFillCommand == AutoFill::AutoFillCommand::SAVE ? + AutoFill::AutoFillWindowType::MODAL_WINDOW : autoFillWindowType; + return autoFillWindowType; +} + void AutoFillManager::SetTimeOutEvent(uint32_t eventId) { HILOG_DEBUG("Called."); @@ -147,7 +267,7 @@ void AutoFillManager::RemoveEvent(uint32_t eventId) } eventHandler_->RemoveEvent(eventId); - std::lock_guard lock(mutexLock_); + std::lock_guard lock(extensionCallbacksMutex_); auto ret = extensionCallbacks_.find(eventId); if (ret != extensionCallbacks_.end()) { extensionCallbacks_.erase(ret); @@ -157,7 +277,7 @@ void AutoFillManager::RemoveEvent(uint32_t eventId) void AutoFillManager::HandleTimeOut(uint32_t eventId) { HILOG_DEBUG("Called."); - std::lock_guard lock(mutexLock_); + std::lock_guard lock(extensionCallbacksMutex_); auto ret = extensionCallbacks_.find(eventId); if (ret == extensionCallbacks_.end()) { HILOG_WARN("Event id is not find."); diff --git a/interfaces/inner_api/auto_fill_manager/src/auto_fill_manager_util.cpp b/interfaces/inner_api/auto_fill_manager/src/auto_fill_manager_util.cpp new file mode 100644 index 0000000000..2f237fba83 --- /dev/null +++ b/interfaces/inner_api/auto_fill_manager/src/auto_fill_manager_util.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2024 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 "auto_fill_manager_util.h" + +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +void AutoFillManagerUtil::ConvertToPopupUIExtensionConfig(const AutoFill::AutoFillCustomConfig &config, + Ace::CustomPopupUIExtensionConfig &popupConfig) +{ + popupConfig.isShowInSubWindow = config.isShowInSubWindow; + popupConfig.inspectorId = config.inspectorId; + popupConfig.nodeId = config.nodeId; + popupConfig.isAutoCancel = config.isAutoCancel; + popupConfig.isEnableArrow = config.isEnableArrow; + popupConfig.isFocusable = false; + if (config.targetSize.has_value()) { + Ace::PopupSize popupSize; + AutoFill::PopupSize targetSize = config.targetSize.value(); + popupSize.unit = ConvertPopupUnit(targetSize.unit); + popupSize.width = static_cast(targetSize.width); + popupSize.height = static_cast(targetSize.height); + popupConfig.targetSize = popupSize; + } + + if (config.targetOffset.has_value()) { + Ace::PopupOffset popupOffset; + AutoFill::PopupOffset targetOffset = config.targetOffset.value(); + popupOffset.unit = ConvertPopupUnit(targetOffset.unit); + popupOffset.deltaX = static_cast(targetOffset.deltaX); + popupOffset.deltaY = static_cast(targetOffset.deltaY); + popupConfig.targetOffset = popupOffset; + } + + Ace::PopupLength popupLength; + if (config.targetSpace.has_value()) { + AutoFill::PopupLength targetSpace = config.targetSpace.value(); + popupLength.unit = ConvertPopupUnit(targetSpace.unit); + popupLength.length = static_cast(targetSpace.length); + popupConfig.targetSpace = popupLength; + } + if (config.arrowOffset.has_value()) { + AutoFill::PopupLength arrowOffset = config.arrowOffset.value(); + popupLength.unit = ConvertPopupUnit(arrowOffset.unit); + popupLength.length = static_cast(arrowOffset.length); + popupConfig.arrowOffset = popupLength; + } + + if (config.placement.has_value()) { + popupConfig.placement = ConvertPopupPlacement(config.placement.value()); + } + + popupConfig.backgroundColor = config.backgroundColor; + popupConfig.maskColor = config.maskColor; + popupConfig.onStateChange = config.onStateChange; +} + +Ace::PopupDimensionUnit AutoFillManagerUtil::ConvertPopupUnit(const AutoFill::PopupDimensionUnit &unit) +{ + Ace::PopupDimensionUnit popupUnit = Ace::PopupDimensionUnit::PX; + switch (unit) { + case AutoFill::PopupDimensionUnit::VP: + popupUnit = Ace::PopupDimensionUnit::VP; + break; + case AutoFill::PopupDimensionUnit::FP: + popupUnit = Ace::PopupDimensionUnit::FP; + break; + case AutoFill::PopupDimensionUnit::PERCENT: + popupUnit = Ace::PopupDimensionUnit::PERCENT; + break; + case AutoFill::PopupDimensionUnit::LPX: + popupUnit = Ace::PopupDimensionUnit::LPX; + break; + case AutoFill::PopupDimensionUnit::AUTO: + popupUnit = Ace::PopupDimensionUnit::AUTO; + break; + case AutoFill::PopupDimensionUnit::CALC: + popupUnit = Ace::PopupDimensionUnit::CALC; + break; + default: + break; + } + return popupUnit; +} + +Ace::PopupPlacement AutoFillManagerUtil::ConvertPopupPlacement(const AutoFill::PopupPlacement &placement) +{ + Ace::PopupPlacement popupPlacement = Ace::PopupPlacement::NONE; + switch (placement) { + case AutoFill::PopupPlacement::LEFT: + popupPlacement = Ace::PopupPlacement::LEFT; + break; + case AutoFill::PopupPlacement::RIGHT: + popupPlacement = Ace::PopupPlacement::RIGHT; + break; + case AutoFill::PopupPlacement::TOP_LEFT: + popupPlacement = Ace::PopupPlacement::TOP_LEFT; + break; + case AutoFill::PopupPlacement::TOP_RIGHT: + popupPlacement = Ace::PopupPlacement::TOP_RIGHT; + break; + case AutoFill::PopupPlacement::BOTTOM_LEFT: + popupPlacement = Ace::PopupPlacement::BOTTOM_LEFT; + break; + case AutoFill::PopupPlacement::BOTTOM_RIGHT: + popupPlacement = Ace::PopupPlacement::BOTTOM_RIGHT; + break; + case AutoFill::PopupPlacement::LEFT_TOP: + popupPlacement = Ace::PopupPlacement::LEFT_TOP; + break; + case AutoFill::PopupPlacement::LEFT_BOTTOM: + popupPlacement = Ace::PopupPlacement::LEFT_BOTTOM; + break; + case AutoFill::PopupPlacement::RIGHT_TOP: + popupPlacement = Ace::PopupPlacement::RIGHT_TOP; + break; + case AutoFill::PopupPlacement::RIGHT_BOTTOM: + popupPlacement = Ace::PopupPlacement::RIGHT_BOTTOM; + break; + default: + HILOG_ERROR("Popup placement is invalid."); + break; + } + return popupPlacement; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/interfaces/kits/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension.h b/interfaces/kits/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension.h index 71edc60fe5..aa46ac50f9 100644 --- a/interfaces/kits/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension.h +++ b/interfaces/kits/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -108,6 +108,13 @@ public: */ void OnBackground() override; + /** + * @brief Used to create an update request. + * + * @param wantParams Indicates the view data of the update request. + */ + void UpdateRequest(const AAFwk::WantParams &wantParams); + private: virtual void BindContext(napi_env env, napi_value obj); napi_value CallObjectMethod(const char *name, napi_value const *argv = nullptr, size_t argc = 0, @@ -122,6 +129,7 @@ private: bool HandleAutoFillCreate(const AAFwk::Want &want, const sptr &sessionInfo); void CallJsOnRequest(const AAFwk::Want &want, const sptr &sessionInfo, const sptr &uiWindow); + void RegisterTransferComponentDataListener(const sptr &uiWindow); JsRuntime& jsRuntime_; std::unique_ptr jsObj_; diff --git a/interfaces/kits/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension_util.h b/interfaces/kits/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension_util.h index c34a7d19a9..2642d516ef 100644 --- a/interfaces/kits/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension_util.h +++ b/interfaces/kits/native/ability/native/auto_fill_extension_ability/js_auto_fill_extension_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -27,6 +27,16 @@ class JsRuntime; struct FillResponse { AbilityBase::ViewData viewData; }; + +enum AutoFillCommand { + NONE, + FILL, + SAVE, + UPDATE, + RESIZE, + INPUT, + RELOAD_IN_MODAL +}; /** * @brief Js autofill extension base. */ @@ -35,10 +45,13 @@ public: explicit JsAutoFillExtensionUtil(const std::unique_ptr &runtime); virtual ~JsAutoFillExtensionUtil(); static napi_value WrapFillRequest(const AAFwk::Want &want, const napi_env env); + static napi_value WrapUpdateRequest(const AAFwk::WantParams &wantParams, const napi_env env); static napi_value WrapViewData(const napi_env env, const AbilityBase::ViewData &viewData); static napi_value WrapPageNodeInfo(const napi_env env, const AbilityBase::PageNodeInfo &pageNodeInfo); + static napi_value WrapRectData(const napi_env env, const AbilityBase::Rect &rect); static void UnwrapViewData(const napi_env env, const napi_value value, AbilityBase::ViewData &viewData); static void UnwrapPageNodeInfo(const napi_env env, const napi_value jsProValue, AbilityBase::PageNodeInfo &node); + static void UnwrapRectData(const napi_env env, const napi_value value, AbilityBase::Rect &rect); static void UnwrapFillResponse(const napi_env env, const napi_value value, FillResponse &response); enum AutoFillResultCode { diff --git a/services/abilitymgr/BUILD.gn b/services/abilitymgr/BUILD.gn index 9ac882f564..41da11d564 100644 --- a/services/abilitymgr/BUILD.gn +++ b/services/abilitymgr/BUILD.gn @@ -112,8 +112,10 @@ config("abilityms_config") { if (target_cpu == "arm") { cflags += [ "-DBINDER_IPC_32BIT" ] } - cflags += - [ "-DKEY_AUTO_FILL_ABILITY=\"${ability_runtime_auto_fill_ability}\"" ] + cflags += [ + "-DKEY_AUTO_FILL_ABILITY=\"${ability_runtime_auto_fill_ability}\"", + "-DKEY_SMART_AUTO_FILL_ABILITY=\"${ability_runtime_smart_auto_fill_ability}\"", + ] } ohos_shared_library("abilityms") { diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index c629552296..de7c7d20ce 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -167,6 +167,7 @@ const std::string STR_PHONE = "phone"; const std::string DEBUG_APP = "debugApp"; const std::string AUTO_FILL_PASSWORD_TPYE = "autoFill/password"; +const std::string AUTO_FILL_SMART_TPYE = "autoFill/smart"; constexpr size_t INDEX_ZERO = 0; constexpr size_t INDEX_ONE = 1; constexpr size_t INDEX_TWO = 2; @@ -2434,11 +2435,16 @@ void AbilityManagerService::SetAutoFillElementName(const sptr &exte { HILOG_DEBUG("Called."); CHECK_POINTER_IS_NULLPTR(extensionSessionInfo); - if (extensionSessionInfo->want.GetStringParam(UIEXTENSION_TYPE_KEY) != AUTO_FILL_PASSWORD_TPYE) { + std::vector argList; + if (extensionSessionInfo->want.GetStringParam(UIEXTENSION_TYPE_KEY) == AUTO_FILL_PASSWORD_TPYE) { + SplitStr(KEY_AUTO_FILL_ABILITY, "/", argList); + } else if (extensionSessionInfo->want.GetStringParam(UIEXTENSION_TYPE_KEY) == AUTO_FILL_SMART_TPYE) { + SplitStr(KEY_SMART_AUTO_FILL_ABILITY, "/", argList); + } else { + HILOG_WARN("It is not autofill type."); return; } - std::vector argList; - SplitStr(KEY_AUTO_FILL_ABILITY, "/", argList); + if (argList.size() != ARGC_THREE) { HILOG_ERROR("Parse auto fill extension element name failed."); return; @@ -8324,7 +8330,8 @@ int AbilityManagerService::CheckCallOtherExtensionPermission(const AbilityReques if (extensionType == AppExecFwk::ExtensionAbilityType::ADS_SERVICE) { return ERR_OK; } - if (extensionType == AppExecFwk::ExtensionAbilityType::AUTO_FILL_PASSWORD) { + if (extensionType == AppExecFwk::ExtensionAbilityType::AUTO_FILL_PASSWORD || + extensionType == AppExecFwk::ExtensionAbilityType::AUTO_FILL_SMART) { if (!abilityRequest.appInfo.isSystemApp) { HILOG_ERROR("The application requesting the call is a non system application."); return CHECK_PERMISSION_FAILED; diff --git a/services/common/include/ui_extension_utils.h b/services/common/include/ui_extension_utils.h index 03017d32b6..b8804c251d 100755 --- a/services/common/include/ui_extension_utils.h +++ b/services/common/include/ui_extension_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -50,7 +50,8 @@ const std::unordered_set UI_EXTENSION_SET = { AppExecFwk::ExtensionAbilityType::SYS_COMMON_UI, AppExecFwk::ExtensionAbilityType::SYSPICKER_NAVIGATION, AppExecFwk::ExtensionAbilityType::SYSPICKER_APPSELECTOR, - AppExecFwk::ExtensionAbilityType::SYSPICKER_CAMERA + AppExecFwk::ExtensionAbilityType::SYSPICKER_CAMERA, + AppExecFwk::ExtensionAbilityType::AUTO_FILL_SMART }; const int EDM_SA_UID = 3057; diff --git a/test/unittest/auto_fill_manager_test/BUILD.gn b/test/unittest/auto_fill_manager_test/BUILD.gn index 2a11c0dd01..ea164aa43a 100644 --- a/test/unittest/auto_fill_manager_test/BUILD.gn +++ b/test/unittest/auto_fill_manager_test/BUILD.gn @@ -27,6 +27,7 @@ ohos_unittest("auto_fill_manager_test") { "${ability_runtime_innerkits_path}/auto_fill_manager/src/auto_fill_event_handler.cpp", "${ability_runtime_innerkits_path}/auto_fill_manager/src/auto_fill_extension_callback.cpp", "${ability_runtime_innerkits_path}/auto_fill_manager/src/auto_fill_manager.cpp", + "${ability_runtime_innerkits_path}/auto_fill_manager/src/auto_fill_manager_util.cpp", "auto_fill_manager_test.cpp", ] diff --git a/test/unittest/auto_fill_manager_test/auto_fill_manager_test.cpp b/test/unittest/auto_fill_manager_test/auto_fill_manager_test.cpp index 881ce45dc5..cf3f5e3ecd 100644 --- a/test/unittest/auto_fill_manager_test/auto_fill_manager_test.cpp +++ b/test/unittest/auto_fill_manager_test/auto_fill_manager_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -51,87 +51,5 @@ void AutoFillManagerTest::SetUp() void AutoFillManagerTest::TearDown() {} - -/** - * @tc.name: RequestAutoFill_0100 - * @tc.desc: RequestAutoFill - */ -HWTEST_F(AutoFillManagerTest, RequestAutoFill_0100, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "AutoFillManagerTest, RequestAutoFill_0100, TestSize.Level1"; - auto& manager = AbilityRuntime::AutoFillManager::GetInstance(); - const AbilityBase::AutoFillType autoFillType = AbilityBase::AutoFillType::UNSPECIFIED; - const AbilityBase::ViewData viewdata; - const std::shared_ptr fillCallback = nullptr; - int32_t result = manager.RequestAutoFill(autoFillType, GetUIContent(), viewdata, fillCallback); - EXPECT_EQ(result, AbilityRuntime::AutoFill::AUTO_FILL_OBJECT_IS_NULL); -} - -/** - * @tc.name: RequestAutoSave_0100 - * @tc.desc: RequestAutoSave - */ -HWTEST_F(AutoFillManagerTest, RequestAutoSave_0100, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "AutoFillManagerTest, RequestAutoSave_0100, TestSize.Level1"; - auto& manager = AbilityRuntime::AutoFillManager::GetInstance(); - const AbilityBase::ViewData viewdata; - const std::shared_ptr saveCallback = nullptr; - int32_t result = manager.RequestAutoSave(GetUIContent(), viewdata, saveCallback); - EXPECT_EQ(result, AbilityRuntime::AutoFill::AUTO_FILL_OBJECT_IS_NULL); -} - -/** - * @tc.name: HandleRequestExecuteInner_0100 - * @tc.desc: HandleRequestExecuteInner - */ -HWTEST_F(AutoFillManagerTest, HandleRequestExecuteInner_0100, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "AutoFillManagerTest, HandleRequestExecuteInner_0100, TestSize.Level1"; - auto& manager = AbilityRuntime::AutoFillManager::GetInstance(); - const AbilityBase::AutoFillType autoFillType = AbilityBase::AutoFillType::UNSPECIFIED; - const AbilityBase::ViewData viewdata; - const std::shared_ptr fillCallback = nullptr; - const std::shared_ptr saveCallback = nullptr; - int32_t result = - manager.HandleRequestExecuteInner(autoFillType, GetUIContent(), viewdata, fillCallback, saveCallback); - EXPECT_EQ(result, AbilityRuntime::AutoFill::AUTO_FILL_OBJECT_IS_NULL); -} - -/** - * @tc.name: SetTimeOutEvent_0100 - * @tc.desc: SetTimeOutEvent - */ -HWTEST_F(AutoFillManagerTest, SetTimeOutEvent_0100, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "AutoFillManagerTest, SetTimeOutEvent_0100, TestSize.Level1"; - auto& manager = AbilityRuntime::AutoFillManager::GetInstance(); - manager.SetTimeOutEvent(1); - EXPECT_EQ(manager.eventId_, 0); -} - -/** - * @tc.name: HandleTimeOut_0100 - * @tc.desc: HandleTimeOut - */ -HWTEST_F(AutoFillManagerTest, HandleTimeOut_0100, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "AutoFillManagerTest, HandleTimeOut_0100, TestSize.Level1"; - auto& manager = AbilityRuntime::AutoFillManager::GetInstance(); - manager.HandleTimeOut(1); - EXPECT_EQ(manager.eventId_, 0); -} - -/** - * @tc.name: RemoveEvent_0100 - * @tc.desc: RemoveEvent - */ -HWTEST_F(AutoFillManagerTest, RemoveEvent_0100, TestSize.Level1) -{ - GTEST_LOG_(INFO) << "AutoFillManagerTest, RemoveEvent_0100, TestSize.Level1"; - auto& manager = AbilityRuntime::AutoFillManager::GetInstance(); - manager.RemoveEvent(1); - EXPECT_EQ(manager.eventId_, 0); -} } // namespace AppExecFwk } // namespace OHOS \ No newline at end of file