!37286 web组件支持自动填充

Merge pull request !37286 from abc/master
This commit is contained in:
openharmony_ci 2024-07-16 07:09:14 +00:00 committed by Gitee
commit 1e698a4ffd
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
10 changed files with 442 additions and 22 deletions

View File

@ -101,6 +101,7 @@ constexpr uint32_t DENSITY_KEY = 0b0100;
constexpr uint32_t POPUPSIZE_HEIGHT = 0;
constexpr uint32_t POPUPSIZE_WIDTH = 0;
constexpr int32_t SEARCH_ELEMENT_TIMEOUT_TIME = 1500;
constexpr int32_t POPUP_CALCULATE_RATIO = 2;
#ifdef _ARM64_
const std::string ASSET_LIBARCH_PATH = "/lib/arm64";
@ -1224,8 +1225,8 @@ bool AceContainer::UpdatePage(int32_t instanceId, int32_t pageId, const std::str
class FillRequestCallback : public AbilityRuntime::IFillRequestCallback {
public:
FillRequestCallback(WeakPtr<NG::PipelineContext> pipelineContext, const RefPtr<NG::FrameNode>& node,
AceAutoFillType autoFillType)
: pipelineContext_(pipelineContext), node_(node), autoFillType_(autoFillType) {}
AceAutoFillType autoFillType, bool isNative = true)
: pipelineContext_(pipelineContext), node_(node), autoFillType_(autoFillType), isNative_(isNative) {}
virtual ~FillRequestCallback() = default;
void OnFillRequestSuccess(const AbilityBase::ViewData& viewData) override
{
@ -1236,6 +1237,19 @@ public:
CHECK_NULL_VOID(taskExecutor);
auto viewDataWrap = ViewDataWrap::CreateViewDataWrap(viewData);
CHECK_NULL_VOID(viewDataWrap);
if (!isNative_) {
auto node = node_.Upgrade();
CHECK_NULL_VOID(node);
taskExecutor->PostTask(
[viewDataWrap, node, autoFillType = autoFillType_]() {
if (node) {
node->NotifyFillRequestSuccess(viewDataWrap, nullptr, autoFillType);
}
},
TaskExecutor::TaskType::UI, "ArkUINotifyWebFillRequestSuccess");
return;
}
taskExecutor->PostTask(
[viewDataWrap, pipelineContext, autoFillType = autoFillType_]() {
if (pipelineContext) {
@ -1262,13 +1276,48 @@ public:
},
TaskExecutor::TaskType::UI, "ArkUINotifyFillRequestFailed");
}
void onPopupConfigWillUpdate(AbilityRuntime::AutoFill::AutoFillCustomConfig& config) override
{
// Non-native component like web/xcomponent, popup always displayed in the center of the hap
// The offset needs to be calculated based on the placement
if (isNative_ || !config.targetSize.has_value() || !config.placement.has_value()) {
return;
}
auto node = node_.Upgrade();
CHECK_NULL_VOID(node);
auto rectf = node->GetRectWithRender();
TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "frame rect:%{public}s", rectf.ToString().c_str());
AbilityRuntime::AutoFill::PopupOffset offset;
AbilityRuntime::AutoFill::PopupPlacement placement = config.placement.value();
AbilityRuntime::AutoFill::PopupSize size = config.targetSize.value();
// only support BOTTOM_XXX AND TOP_XXX
if (placement == AbilityRuntime::AutoFill::PopupPlacement::BOTTOM ||
placement == AbilityRuntime::AutoFill::PopupPlacement::BOTTOM_LEFT ||
placement == AbilityRuntime::AutoFill::PopupPlacement::BOTTOM_RIGHT) {
offset.deltaY = rect_.top + rect_.height +
((size.height + rectf.GetY() - rectf.Height()) / POPUP_CALCULATE_RATIO);
} else {
offset.deltaY = rect_.top + ((rectf.GetY() - size.height - rectf.Height()) / POPUP_CALCULATE_RATIO);
}
TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "popup offset.deltaY:%{public}f", offset.deltaY);
config.targetOffset = offset;
}
void SetFocusedRect(AbilityBase::Rect rect)
{
rect_ = rect;
}
private:
WeakPtr<NG::PipelineContext> pipelineContext_ = nullptr;
WeakPtr<NG::FrameNode> node_ = nullptr;
AceAutoFillType autoFillType_ = AceAutoFillType::ACE_UNSPECIFIED;
bool isNative_ = true;
AbilityBase::Rect rect_;
};
bool AceContainer::UpdatePopupUIExtension(const RefPtr<NG::FrameNode>& node, uint32_t autoFillSessionId)
bool AceContainer::UpdatePopupUIExtension(const RefPtr<NG::FrameNode>& node,
uint32_t autoFillSessionId, bool isNative)
{
CHECK_NULL_RETURN(node, false);
CHECK_NULL_RETURN(uiWindow_, false);
@ -1281,6 +1330,9 @@ bool AceContainer::UpdatePopupUIExtension(const RefPtr<NG::FrameNode>& node, uin
auto viewDataWrapOhos = AceType::DynamicCast<ViewDataWrapOhos>(viewDataWrap);
CHECK_NULL_RETURN(viewDataWrapOhos, false);
auto viewData = viewDataWrapOhos->GetViewData();
if (!isNative) {
OverwritePageNodeInfo(node, viewData);
}
AbilityRuntime::AutoFillManager::GetInstance().UpdateCustomPopupUIExtension(autoFillSessionId, viewData);
return true;
}
@ -1344,8 +1396,62 @@ void AceContainer::FillAutoFillViewData(const RefPtr<NG::FrameNode> &node, RefPt
}
}
void AceContainer::OverwritePageNodeInfo(const RefPtr<NG::FrameNode>& frameNode,
AbilityBase::ViewData& viewData)
{
// Non-native component like web/xcomponent, does not have PageNodeInfo
CHECK_NULL_VOID(frameNode);
auto pattern = frameNode->GetPattern();
CHECK_NULL_VOID(pattern);
std::vector<AbilityBase::PageNodeInfo> nodeInfos;
auto viewDataWrap = ViewDataWrap::CreateViewDataWrap();
pattern->DumpViewDataPageNode(viewDataWrap);
auto infos = viewDataWrap->GetPageNodeInfoWraps();
for (const auto& info : infos) {
if (!info) {
continue;
}
AbilityBase::PageNodeInfo node;
node.id = info->GetId();
node.depth = -1;
node.autoFillType = static_cast<AbilityBase::AutoFillType>(info->GetAutoFillType());
node.isFocus = info->GetIsFocus();
node.value = info->GetValue();
node.placeholder = info->GetPlaceholder();
NG::RectF rectF = info->GetPageNodeRect();
node.rect.left = rectF.GetX();
node.rect.top = rectF.GetY();
node.rect.width = rectF.Width();
node.rect.height = rectF.Height();
nodeInfos.emplace_back(node);
}
viewData.nodes = nodeInfos;
}
void FillAutoFillCustomConfig(const RefPtr<NG::FrameNode>& node,
AbilityRuntime::AutoFill::AutoFillCustomConfig& customConfig)
{
CHECK_NULL_VOID(node);
AbilityRuntime::AutoFill::PopupSize popupSize;
popupSize.height = POPUPSIZE_HEIGHT;
popupSize.width = POPUPSIZE_WIDTH;
customConfig.targetSize = popupSize;
customConfig.isShowInSubWindow = false;
customConfig.nodeId = node->GetId();
customConfig.isEnableArrow = false;
}
void GetFocusedElementRect(const AbilityBase::ViewData& viewData, AbilityBase::Rect& rect)
{
for (const auto& info : viewData.nodes) {
if (info.isFocus) {
rect = info.rect;
}
}
}
bool AceContainer::RequestAutoFill(const RefPtr<NG::FrameNode>& node, AceAutoFillType autoFillType,
bool isNewPassWord, bool& isPopup, uint32_t& autoFillSessionId)
bool isNewPassWord, bool& isPopup, uint32_t& autoFillSessionId, bool isNative)
{
TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "called, autoFillType: %{public}d", static_cast<int32_t>(autoFillType));
auto pipelineContext = AceType::DynamicCast<NG::PipelineContext>(pipelineContext_);
@ -1361,7 +1467,7 @@ bool AceContainer::RequestAutoFill(const RefPtr<NG::FrameNode>& node, AceAutoFil
auto autoFillContainerNode = node->GetFirstAutoFillContainerNode();
uiContentImpl->DumpViewData(autoFillContainerNode, viewDataWrap, true);
FillAutoFillViewData(node, viewDataWrap);
auto callback = std::make_shared<FillRequestCallback>(pipelineContext, node, autoFillType);
auto callback = std::make_shared<FillRequestCallback>(pipelineContext, node, autoFillType, isNative);
auto viewDataWrapOhos = AceType::DynamicCast<ViewDataWrapOhos>(viewDataWrap);
CHECK_NULL_RETURN(viewDataWrapOhos, false);
auto viewData = viewDataWrapOhos->GetViewData();
@ -1371,14 +1477,14 @@ bool AceContainer::RequestAutoFill(const RefPtr<NG::FrameNode>& node, AceAutoFil
callback->OnFillRequestSuccess(viewData);
return true;
}
AbilityRuntime::AutoFill::PopupSize popupSize;
popupSize.height = POPUPSIZE_HEIGHT;
popupSize.width = POPUPSIZE_WIDTH;
if (!isNative) {
OverwritePageNodeInfo(node, viewData);
AbilityBase::Rect rect;
GetFocusedElementRect(viewData, rect);
callback->SetFocusedRect(rect);
}
AbilityRuntime::AutoFill::AutoFillCustomConfig customConfig;
customConfig.targetSize = popupSize;
customConfig.isShowInSubWindow = false;
customConfig.nodeId = node->GetId();
customConfig.isEnableArrow = false;
FillAutoFillCustomConfig(node, customConfig);
AbilityRuntime::AutoFill::AutoFillRequest autoFillRequest;
autoFillRequest.config = customConfig;
autoFillRequest.autoFillType = static_cast<AbilityBase::AutoFillType>(autoFillType);
@ -1441,7 +1547,7 @@ private:
};
bool AceContainer::RequestAutoSave(const RefPtr<NG::FrameNode>& node, const std::function<void()>& onFinish,
const std::function<void()>& onUIExtNodeBindingCompleted)
const std::function<void()>& onUIExtNodeBindingCompleted, bool isNative)
{
TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "called");
CHECK_NULL_RETURN(uiWindow_, false);
@ -1457,6 +1563,9 @@ bool AceContainer::RequestAutoSave(const RefPtr<NG::FrameNode>& node, const std:
auto viewDataWrapOhos = AceType::DynamicCast<ViewDataWrapOhos>(viewDataWrap);
CHECK_NULL_RETURN(viewDataWrapOhos, false);
auto viewData = viewDataWrapOhos->GetViewData();
if (!isNative) {
OverwritePageNodeInfo(node, viewData);
}
AbilityRuntime::AutoFill::AutoFillRequest autoFillRequest;
autoFillRequest.viewData = viewData;
autoFillRequest.autoFillCommand = AbilityRuntime::AutoFill::AutoFillCommand::SAVE;

View File

@ -98,7 +98,8 @@ public:
~AceContainer() override;
bool UpdatePopupUIExtension(const RefPtr<NG::FrameNode>& node, uint32_t autoFillSessionId) override;
bool UpdatePopupUIExtension(const RefPtr<NG::FrameNode>& node,
uint32_t autoFillSessionId, bool isNative = true) override;
void Initialize() override;
@ -562,11 +563,12 @@ public:
bool GetCurPointerEventSourceType(int32_t& sourceType) override;
bool RequestAutoFill(const RefPtr<NG::FrameNode>& node, AceAutoFillType autoFillType,
bool isNewPassWord, bool& isPopup, uint32_t& autoFillSessionId) override;
bool isNewPassWord, bool& isPopup, uint32_t& autoFillSessionId, bool isNative = true) override;
bool IsNeedToCreatePopupWindow(const AceAutoFillType& autoFillType) override;
bool RequestAutoSave(const RefPtr<NG::FrameNode>& node, const std::function<void()>& onFinish,
const std::function<void()>& onUIExtNodeBindingCompleted) override;
const std::function<void()>& onUIExtNodeBindingCompleted, bool isNative = true) override;
std::shared_ptr<NavigationController> GetNavigationController(const std::string& navigationId) override;
void OverwritePageNodeInfo(const RefPtr<NG::FrameNode>& frameNode, AbilityBase::ViewData& viewData);
bool ChangeType(AbilityBase::ViewData& viewData);
AceAutoFillType PlaceHolderToType(const std::string& onePlaceHolder) override;

View File

@ -83,7 +83,8 @@ public:
}
virtual void DestroyView() {}
virtual bool UpdatePopupUIExtension(const RefPtr<NG::FrameNode>& node, uint32_t autoFillSessionId)
virtual bool UpdatePopupUIExtension(const RefPtr<NG::FrameNode>& node,
uint32_t autoFillSessionId, bool isNative = true)
{
return false;
}
@ -247,7 +248,7 @@ public:
{
return false;
}
virtual void SetIsFormRender(bool isFormRender) {};
const std::string& GetCardHapPath() const
@ -489,7 +490,7 @@ public:
}
virtual bool RequestAutoFill(const RefPtr<NG::FrameNode>& node, AceAutoFillType autoFillType,
bool isNewPassWord, bool& isPopup, uint32_t& autoFillSessionId)
bool isNewPassWord, bool& isPopup, uint32_t& autoFillSessionId, bool isNative = true)
{
return false;
}
@ -500,7 +501,7 @@ public:
}
virtual bool RequestAutoSave(const RefPtr<NG::FrameNode>& node, const std::function<void()>& onFinish = nullptr,
const std::function<void()>& onUIExtNodeBindingCompleted = nullptr)
const std::function<void()>& onUIExtNodeBindingCompleted = nullptr, bool isNative = true)
{
return false;
}

View File

@ -2784,6 +2784,23 @@ void WebDelegate::RegisterAvoidAreaChangeListener()
}
}
class NWebAutoFillCallbackImpl : public OHOS::NWeb::NWebMessageValueCallback {
public:
NWebAutoFillCallbackImpl(const WeakPtr<WebDelegate>& delegate) : delegate_(delegate) {}
~NWebAutoFillCallbackImpl() = default;
void OnReceiveValue(std::shared_ptr<NWebMessage> result) override
{
TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "called");
auto delegate = delegate_.Upgrade();
CHECK_NULL_VOID(delegate);
delegate->HandleAutoFillEvent(result);
}
private:
WeakPtr<WebDelegate> delegate_;
};
void WebDelegate::UnregisterAvoidAreaChangeListener()
{
constexpr static int32_t PLATFORM_VERSION_TEN = 10;
@ -2880,6 +2897,8 @@ void WebDelegate::InitWebViewWithSurface()
#ifdef OHOS_STANDARD_SYSTEM
auto screenLockCallback = std::make_shared<NWebScreenLockCallbackImpl>(context);
delegate->nweb_->RegisterScreenLockFunction(Container::CurrentId(), screenLockCallback);
auto autoFillCallback = std::make_shared<NWebAutoFillCallbackImpl>(weak);
delegate->nweb_->SetAutofillCallback(autoFillCallback);
#endif
auto findListenerImpl = std::make_shared<FindListenerImpl>();
findListenerImpl->SetWebDelegate(weak);
@ -5835,6 +5854,30 @@ void WebDelegate::HandleAccessibilityHoverEvent(int32_t x, int32_t y)
}
}
void WebDelegate::NotifyAutoFillViewData(const std::string& jsonStr)
{
auto context = context_.Upgrade();
CHECK_NULL_VOID(context);
context->GetTaskExecutor()->PostTask(
[weak = WeakClaim(this), jsonStr]() {
auto delegate = weak.Upgrade();
CHECK_NULL_VOID(delegate);
CHECK_NULL_VOID(delegate->nweb_);
auto webMessage = std::make_shared<OHOS::NWeb::NWebMessage>(NWebValue::Type::NONE);
webMessage->SetType(NWebValue::Type::STRING);
webMessage->SetString(jsonStr);
delegate->nweb_->FillAutofillData(webMessage);
},
TaskExecutor::TaskType::PLATFORM, "ArkUIWebNotifyAutoFillViewData");
}
void WebDelegate::HandleAutoFillEvent(const std::shared_ptr<OHOS::NWeb::NWebMessage>& viewDataJson)
{
auto pattern = webPattern_.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->HandleAutoFillEvent(viewDataJson);
}
#endif
std::string WebDelegate::GetUrlStringParam(const std::string& param, const std::string& name) const

View File

@ -792,6 +792,8 @@ public:
richtextData_ = richtextData;
}
void HandleAccessibilityHoverEvent(int32_t x, int32_t y);
void NotifyAutoFillViewData(const std::string& jsonStr);
void HandleAutoFillEvent(const std::shared_ptr<OHOS::NWeb::NWebMessage>& viewDataJson);
#endif
void OnErrorReceive(std::shared_ptr<OHOS::NWeb::NWebUrlResourceRequest> request,
std::shared_ptr<OHOS::NWeb::NWebUrlResourceError> error);

View File

@ -1600,7 +1600,7 @@ void FrameNode::ThrottledVisibleTask()
GetVisibleRect(visibleRect, frameRect);
double ratio = IsFrameDisappear() ? VISIBLE_RATIO_MIN
: std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect),
VISIBLE_RATIO_MIN,
VISIBLE_RATIO_MIN,
VISIBLE_RATIO_MAX);
if (NearEqual(ratio, lastThrottledVisibleRatio_)) {
throttledCallbackOnTheWay_ = false;

View File

@ -96,7 +96,7 @@ public:
{
return false;
}
virtual bool CheckCustomAvoidKeyboard() const
{
return false;

View File

@ -42,6 +42,7 @@ build_component_ng("web_pattern_ng") {
]
external_deps = [
"ability_base:view_data",
"ability_runtime:app_manager",
"app_file_service:fileuri_native",
"c_utils:utils",

View File

@ -65,6 +65,8 @@
#include "core/common/ace_engine_ext.h"
#include "core/common/udmf/udmf_client.h"
#include "core/common/udmf/unified_data.h"
#include "page_node_info.h"
#include "auto_fill_type.h"
namespace OHOS::Ace::NG {
namespace {
@ -167,6 +169,49 @@ std::string ParseTextJsonValue(const std::string& textJson)
}
return "";
}
const std::map<std::string, AceAutoFillType> NWEB_AUTOFILL_TYPE_TO_ACE = {
{OHOS::NWeb::NWEB_AUTOFILL_STREET_ADDRESS, AceAutoFillType::ACE_FULL_STREET_ADDRESS},
{OHOS::NWeb::NWEB_AUTOFILL_ADDRESS_LEVEL_3, AceAutoFillType::ACE_DISTRICT_ADDRESS},
{OHOS::NWeb::NWEB_AUTOFILL_ADDRESS_LEVEL_2, AceAutoFillType::ACE_CITY_ADDRESS},
{OHOS::NWeb::NWEB_AUTOFILL_ADDRESS_LEVEL_1, AceAutoFillType::ACE_PROVINCE_ADDRESS},
{OHOS::NWeb::NWEB_AUTOFILL_COUNTRY, AceAutoFillType::ACE_COUNTRY_ADDRESS},
{OHOS::NWeb::NWEB_AUTOFILL_NAME, AceAutoFillType::ACE_PERSON_FULL_NAME},
{OHOS::NWeb::NWEB_AUTOFILL_FAMILY_NAME, AceAutoFillType::ACE_PERSON_LAST_NAME},
{OHOS::NWeb::NWEB_AUTOFILL_GIVEN_NAME, AceAutoFillType::ACE_PERSON_FIRST_NAME},
{OHOS::NWeb::NWEB_AUTOFILL_TEL_NATIONAL, AceAutoFillType::ACE_PHONE_NUMBER},
{OHOS::NWeb::NWEB_AUTOFILL_TEL, AceAutoFillType::ACE_FULL_PHONE_NUMBER},
{OHOS::NWeb::NWEB_AUTOFILL_TEL_COUNTRY_CODE, AceAutoFillType::ACE_PHONE_COUNTRY_CODE},
{OHOS::NWeb::NWEB_AUTOFILL_EMAIL, AceAutoFillType::ACE_EMAIL_ADDRESS},
{OHOS::NWeb::NWEB_AUTOFILL_CC_NUMBER, AceAutoFillType::ACE_BANK_CARD_NUMBER},
{OHOS::NWeb::NWEB_AUTOFILL_ID_CARD_NUMBER, AceAutoFillType::ACE_ID_CARD_NUMBER},
{OHOS::NWeb::NWEB_AUTOFILL_NICKNAME, AceAutoFillType::ACE_NICKNAME},
};
const std::map<AceAutoFillType, std::string> ACE_AUTOFILL_TYPE_TO_NWEB = {
{AceAutoFillType::ACE_FULL_STREET_ADDRESS, OHOS::NWeb::NWEB_AUTOFILL_STREET_ADDRESS},
{AceAutoFillType::ACE_DISTRICT_ADDRESS, OHOS::NWeb::NWEB_AUTOFILL_ADDRESS_LEVEL_3},
{AceAutoFillType::ACE_CITY_ADDRESS, OHOS::NWeb::NWEB_AUTOFILL_ADDRESS_LEVEL_2},
{AceAutoFillType::ACE_PROVINCE_ADDRESS, OHOS::NWeb::NWEB_AUTOFILL_ADDRESS_LEVEL_1},
{AceAutoFillType::ACE_COUNTRY_ADDRESS, OHOS::NWeb::NWEB_AUTOFILL_COUNTRY},
{AceAutoFillType::ACE_PERSON_FULL_NAME, OHOS::NWeb::NWEB_AUTOFILL_NAME},
{AceAutoFillType::ACE_PERSON_LAST_NAME, OHOS::NWeb::NWEB_AUTOFILL_FAMILY_NAME},
{AceAutoFillType::ACE_PERSON_FIRST_NAME, OHOS::NWeb::NWEB_AUTOFILL_GIVEN_NAME},
{AceAutoFillType::ACE_PHONE_NUMBER, OHOS::NWeb::NWEB_AUTOFILL_TEL_NATIONAL},
{AceAutoFillType::ACE_FULL_PHONE_NUMBER, OHOS::NWeb::NWEB_AUTOFILL_TEL},
{AceAutoFillType::ACE_PHONE_COUNTRY_CODE, OHOS::NWeb::NWEB_AUTOFILL_TEL_COUNTRY_CODE},
{AceAutoFillType::ACE_EMAIL_ADDRESS, OHOS::NWeb::NWEB_AUTOFILL_EMAIL},
{AceAutoFillType::ACE_BANK_CARD_NUMBER, OHOS::NWeb::NWEB_AUTOFILL_CC_NUMBER},
{AceAutoFillType::ACE_ID_CARD_NUMBER, OHOS::NWeb::NWEB_AUTOFILL_ID_CARD_NUMBER},
{AceAutoFillType::ACE_NICKNAME, OHOS::NWeb::NWEB_AUTOFILL_NICKNAME},
};
const std::map<std::string, OHOS::NWeb::NWebAutofillEvent> NWEB_AUTOFILL_EVENTS = {
{OHOS::NWeb::NWEB_AUTOFILL_EVENT_SAVE, OHOS::NWeb::NWebAutofillEvent::SAVE},
{OHOS::NWeb::NWEB_AUTOFILL_EVENT_FILL, OHOS::NWeb::NWebAutofillEvent::FILL},
{OHOS::NWeb::NWEB_AUTOFILL_EVENT_UPDATE, OHOS::NWeb::NWebAutofillEvent::UPDATE},
{OHOS::NWeb::NWEB_AUTOFILL_EVENT_CLOSE, OHOS::NWeb::NWebAutofillEvent::CLOSE},
};
} // namespace
constexpr int32_t SINGLE_CLICK_NUM = 1;
@ -3245,6 +3290,203 @@ void WebPattern::OnQuickMenuDismissed()
CloseSelectOverlay();
}
void WebPattern::DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap)
{
TAG_LOGI(AceLogTag::ACE_WEB, "called");
CHECK_NULL_VOID(viewDataWrap);
for (const auto& nodeInfo : pageNodeInfo_) {
if (nodeInfo) {
viewDataWrap->AddPageNodeInfoWrap(nodeInfo);
}
}
}
void WebPattern::NotifyFillRequestSuccess(RefPtr<ViewDataWrap> viewDataWrap,
RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType)
{
TAG_LOGI(AceLogTag::ACE_WEB, "called");
CHECK_NULL_VOID(viewDataWrap);
auto nodeInfoWraps = viewDataWrap->GetPageNodeInfoWraps();
auto jsonNode = JsonUtil::Create(true);
for (const auto& nodeInfoWrap : nodeInfoWraps) {
if (nodeInfoWrap == nullptr) {
continue;
}
auto type = nodeInfoWrap->GetAutoFillType();
// white list check
if (ACE_AUTOFILL_TYPE_TO_NWEB.count(type) != 0) {
std::string key = ACE_AUTOFILL_TYPE_TO_NWEB.at(type);
jsonNode->Put(key.c_str(), nodeInfoWrap->GetValue().c_str());
}
}
delegate_->NotifyAutoFillViewData(jsonNode->ToString());
}
void WebPattern::NotifyFillRequestFailed(int32_t errCode, const std::string& fillContent, bool isPopup)
{
TAG_LOGI(AceLogTag::ACE_WEB, "called, errCode:%{public}d", errCode);
}
void WebPattern::ParseViewDataNumber(const std::string& key, int32_t value,
RefPtr<PageNodeInfoWrap> node, RectT<float>& rect, float viewScale)
{
CHECK_NULL_VOID(viewScale > 0);
CHECK_NULL_VOID(node);
std::optional<OffsetF> offset = GetCoordinatePoint();
if (key == OHOS::NWeb::NWEB_VIEW_DATA_KEY_FOCUS) {
node->SetIsFocus(static_cast<bool>(value));
} else if (key == OHOS::NWeb::NWEB_VIEW_DATA_KEY_RECT_X) {
float x = value / viewScale;
rect.SetLeft(x + offset.value_or(OffsetF()).GetX());
} else if (key == OHOS::NWeb::NWEB_VIEW_DATA_KEY_RECT_Y) {
float y = value / viewScale;
rect.SetTop(y + offset.value_or(OffsetF()).GetY());
} else if (key == OHOS::NWeb::NWEB_VIEW_DATA_KEY_RECT_W) {
rect.SetWidth(value / viewScale);
} else if (key == OHOS::NWeb::NWEB_VIEW_DATA_KEY_RECT_H) {
rect.SetHeight(value / viewScale);
}
}
void ParseViewDataString(const std::string& key,
const std::string& value, RefPtr<PageNodeInfoWrap> node)
{
CHECK_NULL_VOID(node);
if (key == OHOS::NWeb::NWEB_VIEW_DATA_KEY_VALUE) {
node->SetValue(value);
} else if (key == OHOS::NWeb::NWEB_VIEW_DATA_KEY_PLACEHOLDER) {
node->SetPlaceholder(value);
}
}
void WebPattern::ParseNWebViewDataNode(std::unique_ptr<JsonValue> child,
std::vector<RefPtr<PageNodeInfoWrap>>& nodeInfos, int32_t nodeId)
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto pipelineContext = host->GetContextRefPtr();
CHECK_NULL_VOID(pipelineContext);
float viewScale = pipelineContext->GetViewScale();
CHECK_NULL_VOID(viewScale > 0);
RefPtr<PageNodeInfoWrap> node = PageNodeInfoWrap::CreatePageNodeInfoWrap();
std::string attribute = child->GetKey();
// white list check
if (NWEB_AUTOFILL_TYPE_TO_ACE.count(attribute) != 0) {
AceAutoFillType type = NWEB_AUTOFILL_TYPE_TO_ACE.at(attribute);
node->SetAutoFillType(type);
} else {
return;
}
RectT<float> rect;
int32_t len = child->GetArraySize();
for (int32_t index = 0; index < len; index++) {
auto object = child->GetArrayItem(index);
if (object == nullptr || !object->IsObject()) {
continue;
}
for (auto child = object->GetChild(); child && !child->IsNull(); child = child->GetNext()) {
if (child->IsString()) {
ParseViewDataString(child->GetKey(), child->GetString(), node);
} else if (child->IsNumber()) {
ParseViewDataNumber(child->GetKey(), child->GetInt(), node, rect, viewScale);
}
}
}
NG::RectF rectF;
rectF.SetRect(rect.GetX(), rect.GetY(), rect.Width(), rect.Height());
node->SetPageNodeRect(rectF);
node->SetId(nodeId);
node->SetDepth(-1);
nodeInfos.emplace_back(node);
}
void WebPattern::ParseNWebViewDataJson(const std::shared_ptr<OHOS::NWeb::NWebMessage>& viewDataJson,
std::vector<RefPtr<PageNodeInfoWrap>>& nodeInfos, OHOS::NWeb::NWebAutofillEvent& eventType)
{
nodeInfos.clear();
auto sourceJson = JsonUtil::ParseJsonString(viewDataJson->GetString());
if (sourceJson == nullptr || sourceJson->IsNull()) {
return;
}
int32_t nodeId = 1;
int32_t len = sourceJson->GetArraySize();
for (int32_t index = 0; index < len; index++) {
auto object = sourceJson->GetArrayItem(index);
if (object == nullptr || !object->IsObject()) {
continue;
}
auto child = object->GetChild();
if (child == nullptr || child->IsNull()) {
continue;
}
if (child->IsString()) {
std::string value = child->GetString();
if (NWEB_AUTOFILL_EVENTS.count(value) != 0) {
OHOS::NWeb::NWebAutofillEvent event = NWEB_AUTOFILL_EVENTS.at(value);
eventType = event;
}
} else if (child->IsArray()) {
ParseNWebViewDataNode(std::move(child), nodeInfos, nodeId);
nodeId++;
}
}
}
void WebPattern::HandleAutoFillEvent(const std::shared_ptr<OHOS::NWeb::NWebMessage>& viewDataJson)
{
TAG_LOGI(AceLogTag::ACE_WEB, "called");
OHOS::NWeb::NWebAutofillEvent eventType = OHOS::NWeb::NWebAutofillEvent::UNKNOWN;
ParseNWebViewDataJson(viewDataJson, pageNodeInfo_, eventType);
if (eventType == OHOS::NWeb::NWebAutofillEvent::SAVE) {
RequestAutoSave();
} else if (eventType == OHOS::NWeb::NWebAutofillEvent::FILL) {
for (const auto& nodeInfo : pageNodeInfo_) {
if (nodeInfo && nodeInfo->GetIsFocus()) {
RequestAutoFill(static_cast<AceAutoFillType>(nodeInfo->GetAutoFillType()));
break;
}
}
} else if (eventType == OHOS::NWeb::NWebAutofillEvent::UPDATE) {
UpdateAutoFillPopup();
} else if (eventType == OHOS::NWeb::NWebAutofillEvent::CLOSE) {
// do nothing, popup is automically cancel when losing focus
}
}
bool WebPattern::RequestAutoFill(AceAutoFillType autoFillType)
{
TAG_LOGI(AceLogTag::ACE_WEB, "called");
auto host = GetHost();
CHECK_NULL_RETURN(host, false);
auto container = Container::Current();
CHECK_NULL_RETURN(container, false);
bool isPopup = false;
return container->RequestAutoFill(host, autoFillType, false, isPopup, autoFillSessionId_, false);
}
bool WebPattern::RequestAutoSave()
{
TAG_LOGI(AceLogTag::ACE_WEB, "called");
auto host = GetHost();
CHECK_NULL_RETURN(host, false);
auto container = Container::Current();
CHECK_NULL_RETURN(container, false);
return container->RequestAutoSave(host, nullptr, nullptr, false);
}
bool WebPattern::UpdateAutoFillPopup()
{
TAG_LOGI(AceLogTag::ACE_WEB, "called");
auto host = GetHost();
CHECK_NULL_RETURN(host, false);
auto container = Container::Current();
CHECK_NULL_RETURN(container, false);
return container->UpdatePopupUIExtension(host, autoFillSessionId_, false);
}
void WebPattern::UpdateSelectHandleInfo()
{
bool needReverse = IsSelectHandleReverse();

View File

@ -25,6 +25,7 @@
#include "base/thread/cancelable_callback.h"
#include "base/utils/utils.h"
#include "base/geometry/axis.h"
#include "base/web/webview/ohos_nweb/include/nweb_autofill.h"
#include "base/web/webview/ohos_nweb/include/nweb_handler.h"
#include "core/common/udmf/unified_data.h"
#include "core/components/dialog/dialog_properties.h"
@ -189,6 +190,13 @@ public:
void OnModifyDone() override;
void DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap) override;
void NotifyFillRequestSuccess(RefPtr<ViewDataWrap> viewDataWrap,
RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType) override;
void NotifyFillRequestFailed(int32_t errCode, const std::string& fillContent = "", bool isPopup = false) override;
void SetWebSrc(const std::string& webSrc)
{
if (webSrc_ != webSrc_) {
@ -526,6 +534,16 @@ public:
{
isCurrentStartHandleDragging_ = isStartHandle;
}
void ParseViewDataNumber(const std::string& key, int32_t value,
RefPtr<PageNodeInfoWrap> node, RectT<float>& rect, float viewScale);
void ParseNWebViewDataNode(std::unique_ptr<JsonValue> child,
std::vector<RefPtr<PageNodeInfoWrap>>& nodeInfos, int32_t nodeId);
void ParseNWebViewDataJson(const std::shared_ptr<OHOS::NWeb::NWebMessage>& viewDataJson,
std::vector<RefPtr<PageNodeInfoWrap>>& nodeInfos, OHOS::NWeb::NWebAutofillEvent& eventType);
void HandleAutoFillEvent(const std::shared_ptr<OHOS::NWeb::NWebMessage>& viewDataJson);
bool RequestAutoFill(AceAutoFillType autoFillType);
bool RequestAutoSave();
bool UpdateAutoFillPopup();
void UpdateSelectHandleInfo();
bool IsSelectHandleReverse();
void OnCompleteSwapWithNewSize();
@ -1029,6 +1047,8 @@ private:
bool textBlurAccessibilityEnable_ = false;
TextBlurCallback textBlurCallback_ = nullptr;
WebComponentClickCallback webComponentClickCallback_ = nullptr;
uint32_t autoFillSessionId_ = 0;
std::vector<RefPtr<PageNodeInfoWrap>> pageNodeInfo_;
};
} // namespace OHOS::Ace::NG