Handle Enter/Space key events for read-only check box and radio button.
Currently if the user tabs onto a read-only check box or radio button,
pressing any character or just space/enter checks/unchecks the controls.
This CL adds a check for read-only flag in the PWL control (Check Box/
Radio Button), before processing the OnChar event.
If the window created for the control is read-only in the CFFL_Checkbox
and CFFL_RadioButton, altering the state of the control is not allowed.
Bug: pdfium:1431
Change-Id: I6fcf8de0c01d973157641fde9bc2579483878484
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/66832
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Himadri Kakar <hikakar@microsoft.com>
diff --git a/fpdfsdk/formfiller/cffl_checkbox.cpp b/fpdfsdk/formfiller/cffl_checkbox.cpp
index 47e158f..4cb4a02 100644
--- a/fpdfsdk/formfiller/cffl_checkbox.cpp
+++ b/fpdfsdk/formfiller/cffl_checkbox.cpp
@@ -63,7 +63,7 @@
CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
CPWL_CheckBox* pWnd = GetCheckBox(pPageView, true);
- if (pWnd) {
+ if (pWnd && !pWnd->IsReadOnly()) {
CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pAnnot);
pWnd->SetCheck(!pWidget->IsChecked());
}
diff --git a/fpdfsdk/formfiller/cffl_radiobutton.cpp b/fpdfsdk/formfiller/cffl_radiobutton.cpp
index 90a4fd9..670197e 100644
--- a/fpdfsdk/formfiller/cffl_radiobutton.cpp
+++ b/fpdfsdk/formfiller/cffl_radiobutton.cpp
@@ -58,7 +58,7 @@
CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
CPWL_RadioButton* pWnd = GetRadioButton(pPageView, true);
- if (pWnd)
+ if (pWnd && !pWnd->IsReadOnly())
pWnd->SetCheck(true);
return CommitData(pPageView, nFlags);
}
diff --git a/fpdfsdk/fpdf_formfill_embeddertest.cpp b/fpdfsdk/fpdf_formfill_embeddertest.cpp
index eee623b..56917e2 100644
--- a/fpdfsdk/fpdf_formfill_embeddertest.cpp
+++ b/fpdfsdk/fpdf_formfill_embeddertest.cpp
@@ -1021,6 +1021,75 @@
UnloadPage(page);
}
+TEST_F(FPDFFormFillEmbedderTest, CheckReadOnlyInCheckbox) {
+ EmbedderTestTimerHandlingDelegate delegate;
+ SetDelegate(&delegate);
+
+ ASSERT_TRUE(OpenDocument("click_form.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ {
+ // Check for read-only checkbox.
+ ScopedFPDFAnnotation focused_annot(FPDFPage_GetAnnot(page, 1));
+ ASSERT_TRUE(FORM_SetFocusedAnnot(form_handle(), focused_annot.get()));
+
+ // Shift-tab to the previous control.
+ ASSERT_TRUE(FORM_OnKeyDown(form_handle(), page, FWL_VKEY_Tab,
+ FWL_EVENTFLAG_ShiftKey));
+ FPDF_ANNOTATION annot = nullptr;
+ int page_index = -1;
+ ASSERT_TRUE(FORM_GetFocusedAnnot(form_handle(), &page_index, &annot));
+ EXPECT_EQ(0, FPDFPage_GetAnnotIndex(page, annot));
+
+ // The read-only checkbox is initially in checked state.
+ EXPECT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot));
+
+ EXPECT_TRUE(FORM_OnChar(form_handle(), page, FWL_VKEY_Return, 0));
+ EXPECT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot));
+
+ EXPECT_TRUE(FORM_OnChar(form_handle(), page, FWL_VKEY_Space, 0));
+ EXPECT_TRUE(FPDFAnnot_IsChecked(form_handle(), annot));
+
+ FPDFPage_CloseAnnot(annot);
+ }
+ UnloadPage(page);
+}
+
+TEST_F(FPDFFormFillEmbedderTest, CheckReadOnlyInRadiobutton) {
+ EmbedderTestTimerHandlingDelegate delegate;
+ SetDelegate(&delegate);
+
+ ASSERT_TRUE(OpenDocument("click_form.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ {
+ // Check for read-only radio button.
+ ScopedFPDFAnnotation focused_annot(FPDFPage_GetAnnot(page, 1));
+ ASSERT_TRUE(FORM_SetFocusedAnnot(form_handle(), focused_annot.get()));
+
+ // Tab to the next control.
+ ASSERT_TRUE(FORM_OnKeyDown(form_handle(), page, FWL_VKEY_Tab, 0));
+
+ FPDF_ANNOTATION annot = nullptr;
+ int page_index = -1;
+ ASSERT_TRUE(FORM_GetFocusedAnnot(form_handle(), &page_index, &annot));
+ EXPECT_EQ(2, FPDFPage_GetAnnotIndex(page, annot));
+ // The read-only radio button is initially in checked state.
+ EXPECT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot));
+
+ EXPECT_TRUE(FORM_OnChar(form_handle(), page, FWL_VKEY_Return, 0));
+ EXPECT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot));
+
+ EXPECT_TRUE(FORM_OnChar(form_handle(), page, FWL_VKEY_Space, 0));
+ EXPECT_FALSE(FPDFAnnot_IsChecked(form_handle(), annot));
+
+ FPDFPage_CloseAnnot(annot);
+ }
+ UnloadPage(page);
+}
+
#ifdef PDF_ENABLE_V8
TEST_F(FPDFFormFillEmbedderTest, DisableJavaScript) {
// Test that timers and intervals can't fire without JS.
diff --git a/fpdfsdk/pwl/cpwl_special_button.cpp b/fpdfsdk/pwl/cpwl_special_button.cpp
index e653ae1..215df40 100644
--- a/fpdfsdk/pwl/cpwl_special_button.cpp
+++ b/fpdfsdk/pwl/cpwl_special_button.cpp
@@ -39,6 +39,9 @@
}
bool CPWL_CheckBox::OnChar(uint16_t nChar, uint32_t nFlag) {
+ if (IsReadOnly())
+ return false;
+
SetCheck(!IsChecked());
return true;
}
@@ -59,6 +62,9 @@
}
bool CPWL_RadioButton::OnChar(uint16_t nChar, uint32_t nFlag) {
+ if (IsReadOnly())
+ return false;
+
SetCheck(true);
return true;
}
diff --git a/fpdfsdk/pwl/cpwl_special_button_embeddertest.cpp b/fpdfsdk/pwl/cpwl_special_button_embeddertest.cpp
index c99e488..ef50ef4 100644
--- a/fpdfsdk/pwl/cpwl_special_button_embeddertest.cpp
+++ b/fpdfsdk/pwl/cpwl_special_button_embeddertest.cpp
@@ -108,13 +108,10 @@
TEST_F(CPWLSpecialButtonEmbedderTest, EnterOnReadOnlyCheckBox) {
FormFillerAndWindowSetup(GetCPDFSDKAnnotReadOnlyCheckBox());
CPWL_CheckBox* check_box = static_cast<CPWL_CheckBox*>(GetWindow());
+ EXPECT_TRUE(check_box->IsChecked());
EXPECT_TRUE(GetCPDFSDKFormFillEnv()->GetInteractiveFormFiller()->OnChar(
GetCPDFSDKAnnotReadOnlyCheckBox(), '\r', 0));
- // The check box is checked by default. Since it is a read only checkbox,
- // clicking Enter shouldn't change its state.
- // TODO(http://crbug.com/pdfium/1431) : Change this to EXPECT_TRUE
- // as part of the fix.
- EXPECT_FALSE(check_box->IsChecked());
+ EXPECT_TRUE(check_box->IsChecked());
}
TEST_F(CPWLSpecialButtonEmbedderTest, EnterOnCheckBox) {
@@ -132,11 +129,10 @@
TEST_F(CPWLSpecialButtonEmbedderTest, EnterOnReadOnlyRadioButton) {
FormFillerAndWindowSetup(GetCPDFSDKAnnotReadOnlyRadioButton());
CPWL_RadioButton* radio_button = static_cast<CPWL_RadioButton*>(GetWindow());
+ EXPECT_FALSE(radio_button->IsChecked());
EXPECT_TRUE(GetCPDFSDKFormFillEnv()->GetInteractiveFormFiller()->OnChar(
GetCPDFSDKAnnotReadOnlyRadioButton(), '\r', 0));
- // TODO(http://crbug.com/pdfium/1431) : Change this to EXPECT_FALSE
- // as part of the fix.
- EXPECT_TRUE(radio_button->IsChecked());
+ EXPECT_FALSE(radio_button->IsChecked());
}
TEST_F(CPWLSpecialButtonEmbedderTest, EnterOnRadioButton) {