已合并
fix(web): add text share eligibility check for web selection #77573
jerrywangxmu创建于 2025年12月9日
fix(web): add text share eligibility check for web selection #77573
已合并
共 3 个文件变更+123-1
| @@ -20,6 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | + | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | 26 | ||
| @@ -1283,6 +1284,22 @@ void WebSelectOverlay::OnUpdateSelectOverlayInfo(SelectOverlayInfo &selectInfo, | |||
| 1283 | } | 1284 | } |
| 1284 | } | 1285 | } |
| 1285 | 1286 | ||
| 1287 | +bool WebSelectOverlay::IsNeedMenuShareForWeb() | ||
| 1288 | +{ | ||
| 1289 | + const auto& shareContent = GetSelectedText(); | ||
| 1290 | + std::string_view sv(shareContent); | ||
| 1291 | + // whitespace characters to trim (same as \s in regex for ASCII whitespace) | ||
| 1292 | + constexpr auto ws = " \t\n\r\f\v"; | ||
| 1293 | + const auto start = sv.find_first_not_of(ws); | ||
| 1294 | + if (start == std::string_view::npos) { | ||
| 1295 | + return false; | ||
| 1296 | + } | ||
| 1297 | + const auto end = sv.find_last_not_of(ws); | ||
| 1298 | + const auto trimmedLen = end - start + 1; | ||
| 1299 | + const auto maxShareLength = static_cast<size_t>(TextShareAdapter::GetMaxTextShareLength()); | ||
| 1300 | + return trimmedLen <= maxShareLength; | ||
| 1301 | +} | ||
| 1302 | + | ||
| 1286 | void WebSelectOverlay::OnHandleMarkInfoChange( | 1303 | void WebSelectOverlay::OnHandleMarkInfoChange( |
| 1287 | const std::shared_ptr<SelectOverlayInfo> info, SelectOverlayDirtyFlag flag) | 1304 | const std::shared_ptr<SelectOverlayInfo> info, SelectOverlayDirtyFlag flag) |
| 1288 | { | 1305 | { |
| @@ -1300,7 +1317,7 @@ void WebSelectOverlay::OnHandleMarkInfoChange( | |||
| 1300 | auto copyOption = delegate->GetCopyOptionMode(); | 1317 | auto copyOption = delegate->GetCopyOptionMode(); |
| 1301 | bool canCopyOut = (copyOption != OHOS::NWeb::NWebPreference::CopyOptionMode::NONE) && | 1318 | bool canCopyOut = (copyOption != OHOS::NWeb::NWebPreference::CopyOptionMode::NONE) && |
| 1302 | (copyOption != OHOS::NWeb::NWebPreference::CopyOptionMode::IN_APP); | 1319 | (copyOption != OHOS::NWeb::NWebPreference::CopyOptionMode::IN_APP); |
| 1303 | - if (info->menuInfo.showShare != (IsSupportMenuShare() && IsNeedMenuShare())) { | 1320 | + if (info->menuInfo.showShare != (IsSupportMenuShare() && IsNeedMenuShareForWeb())) { |
| 1304 | info->menuInfo.showShare = !info->menuInfo.showShare && canCopyOut; | 1321 | info->menuInfo.showShare = !info->menuInfo.showShare && canCopyOut; |
| 1305 | manager->NotifyUpdateToolBar(true); | 1322 | manager->NotifyUpdateToolBar(true); |
| 1306 | } | 1323 | } |
| @@ -104,6 +104,7 @@ public: | |||
| 104 | void SetEditMenuOptions(SelectOverlayInfo& selectInfo); | 104 | void SetEditMenuOptions(SelectOverlayInfo& selectInfo); |
| 105 | void UpdateSelectHandleInfo(); | 105 | void UpdateSelectHandleInfo(); |
| 106 | bool IsSelectHandleReverse(); | 106 | bool IsSelectHandleReverse(); |
| 107 | + bool IsNeedMenuShareForWeb(); | ||
| 107 | // Check whether the handle status is valid. | 108 | // Check whether the handle status is valid. |
| 108 | WebOverlayType GetTouchHandleOverlayType( | 109 | WebOverlayType GetTouchHandleOverlayType( |
| 109 | std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle, | 110 | std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle, |
| @@ -7089,6 +7089,110 @@ HWTEST_F(WebSelectOverlayTest, IsMouseInHandleRect, TestSize.Level1) | |||
| 7089 | 7089 | ||
| 7090 | } | 7090 | } |
| 7091 | 7091 | ||
| 7092 | +/** | ||
| 7093 | + * @tc.name: IsNeedMenuShareForWeb | ||
| 7094 | + * @tc.desc: Test IsNeedMenuShareForWeb. | ||
| 7095 | + * @tc.type: FUNC | ||
| 7096 | + */ | ||
| 7097 | +HWTEST_F(WebSelectOverlayTest, IsNeedMenuShareForWeb, TestSize.Level1) | ||
| 7098 | +{ | ||
| 7099 | + | ||
| 7100 | + auto* stack = ViewStackProcessor::GetInstance(); | ||
| 7101 | + ASSERT_NE(stack, nullptr); | ||
| 7102 | + auto nodeId = stack->ClaimNodeId(); | ||
| 7103 | + auto frameNode = | ||
| 7104 | + FrameNode::GetOrCreateFrameNode(V2::WEB_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<WebPattern>(); }); | ||
| 7105 | + stack->Push(frameNode); | ||
| 7106 | + auto webPattern = frameNode->GetPattern<WebPattern>(); | ||
| 7107 | + ASSERT_NE(webPattern, nullptr); | ||
| 7108 | + webPattern->OnModifyDone(); | ||
| 7109 | + WebSelectOverlay overlay(webPattern); | ||
| 7110 | + OHOS::Ace::SetReturnStatus(""); | ||
| 7111 | + EXPECT_FALSE(overlay.IsNeedMenuShareForWeb()); | ||
| 7112 | + OHOS::Ace::SetReturnStatus(" "); | ||
| 7113 | + EXPECT_FALSE(overlay.IsNeedMenuShareForWeb()); | ||
| 7114 | + OHOS::Ace::SetReturnStatus(""); | ||
| 7115 | + | ||
| 7116 | +} | ||
| 7117 | + | ||
| 7118 | +/** | ||
| 7119 | + * @tc.name: IsNeedMenuShareForWeb_TrimInvariant | ||
TDD结果附一下 ![]() ![]() | |||
| 7120 | + * @tc.desc: Verify ASCII whitespace trimming does not change share eligibility. | ||
| 7121 | + * @tc.type: FUNC | ||
| 7122 | + */ | ||
| 7123 | +HWTEST_F(WebSelectOverlayTest, IsNeedMenuShareForWeb_TrimInvariant, TestSize.Level1) | ||
| 7124 | +{ | ||
| 7125 | + | ||
| 7126 | + auto* stack = ViewStackProcessor::GetInstance(); | ||
| 7127 | + ASSERT_NE(stack, nullptr); | ||
| 7128 | + auto nodeId = stack->ClaimNodeId(); | ||
| 7129 | + auto frameNode = | ||
| 7130 | + FrameNode::GetOrCreateFrameNode(V2::WEB_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<WebPattern>(); }); | ||
已review ![]() ![]() | |||
| 7131 | + stack->Push(frameNode); | ||
| 7132 | + auto webPattern = frameNode->GetPattern<WebPattern>(); | ||
| 7133 | + ASSERT_NE(webPattern, nullptr); | ||
| 7134 | + webPattern->OnModifyDone(); | ||
| 7135 | + WebSelectOverlay overlay(webPattern); | ||
| 7136 | + OHOS::Ace::SetReturnStatus(" \t\nabc\r\f\v "); | ||
| 7137 | + bool resTrim = overlay.IsNeedMenuShareForWeb(); | ||
| 7138 | + OHOS::Ace::SetReturnStatus("abc"); | ||
| 7139 | + bool resPlain = overlay.IsNeedMenuShareForWeb(); | ||
| 7140 | + EXPECT_EQ(resTrim, resPlain); | ||
| 7141 | + OHOS::Ace::SetReturnStatus(""); | ||
| 7142 | + | ||
| 7143 | +} | ||
| 7144 | + | ||
| 7145 | +/** | ||
| 7146 | + * @tc.name: IsNeedMenuShareForWeb_MonotonicByLength | ||
| 7147 | + * @tc.desc: If longer text is eligible for share, shorter text must also be eligible. | ||
| 7148 | + * @tc.type: FUNC | ||
| 7149 | + */ | ||
| 7150 | +HWTEST_F(WebSelectOverlayTest, IsNeedMenuShareForWeb_MonotonicByLength, TestSize.Level1) | ||
| 7151 | +{ | ||
| 7152 | + | ||
| 7153 | + auto* stack = ViewStackProcessor::GetInstance(); | ||
| 7154 | + ASSERT_NE(stack, nullptr); | ||
| 7155 | + auto nodeId = stack->ClaimNodeId(); | ||
| 7156 | + auto frameNode = | ||
| 7157 | + FrameNode::GetOrCreateFrameNode(V2::WEB_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<WebPattern>(); }); | ||
| 7158 | + stack->Push(frameNode); | ||
| 7159 | + auto webPattern = frameNode->GetPattern<WebPattern>(); | ||
| 7160 | + ASSERT_NE(webPattern, nullptr); | ||
| 7161 | + webPattern->OnModifyDone(); | ||
| 7162 | + WebSelectOverlay overlay(webPattern); | ||
| 7163 | + OHOS::Ace::SetReturnStatus("aa"); | ||
| 7164 | + bool resLong = overlay.IsNeedMenuShareForWeb(); | ||
| 7165 | + OHOS::Ace::SetReturnStatus("a"); | ||
| 7166 | + bool resShort = overlay.IsNeedMenuShareForWeb(); | ||
| 7167 | + EXPECT_TRUE(!resLong || resShort); | ||
| 7168 | + OHOS::Ace::SetReturnStatus(""); | ||
| 7169 | + | ||
| 7170 | +} | ||
| 7171 | + | ||
| 7172 | +/** | ||
| 7173 | + * @tc.name: IsNeedMenuShareForWeb_WhitespaceVariants | ||
| 7174 | + * @tc.desc: Only ASCII whitespace text should be ineligible for sharing. | ||
| 7175 | + * @tc.type: FUNC | ||
| 7176 | + */ | ||
| 7177 | +HWTEST_F(WebSelectOverlayTest, IsNeedMenuShareForWeb_WhitespaceVariants, TestSize.Level1) | ||
| 7178 | +{ | ||
| 7179 | + | ||
| 7180 | + auto* stack = ViewStackProcessor::GetInstance(); | ||
| 7181 | + ASSERT_NE(stack, nullptr); | ||
| 7182 | + auto nodeId = stack->ClaimNodeId(); | ||
| 7183 | + auto frameNode = | ||
| 7184 | + FrameNode::GetOrCreateFrameNode(V2::WEB_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<WebPattern>(); }); | ||
| 7185 | + stack->Push(frameNode); | ||
| 7186 | + auto webPattern = frameNode->GetPattern<WebPattern>(); | ||
| 7187 | + ASSERT_NE(webPattern, nullptr); | ||
| 7188 | + webPattern->OnModifyDone(); | ||
| 7189 | + WebSelectOverlay overlay(webPattern); | ||
| 7190 | + OHOS::Ace::SetReturnStatus("\t\n\r\f\v "); | ||
| 7191 | + EXPECT_FALSE(overlay.IsNeedMenuShareForWeb()); | ||
| 7192 | + OHOS::Ace::SetReturnStatus(""); | ||
| 7193 | + | ||
| 7194 | +} | ||
| 7195 | + | ||
| 7092 | /** | 7196 | /** |
| 7093 | * @tc.name: OnOverlayMouseEvent | 7197 | * @tc.name: OnOverlayMouseEvent |
| 7094 | * @tc.desc: Test OnOverlayMouseEvent. | 7198 | * @tc.desc: Test OnOverlayMouseEvent. |


转换是否必要,是因为下面判断的静态告警吗