1 // Copyright 2017 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "fpdfsdk/cpdfsdk_annot.h"
6 #include "fpdfsdk/cpdfsdk_annotiterator.h"
7 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
8 #include "fpdfsdk/cpdfsdk_helpers.h"
9 #include "fpdfsdk/formfiller/cffl_formfiller.h"
10 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
11 #include "fpdfsdk/pwl/cpwl_combo_box.h"
12 #include "fpdfsdk/pwl/cpwl_wnd.h"
13 #include "public/fpdf_fwlevent.h"
14 #include "testing/embedder_test.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 class CPWLComboBoxEditEmbedderTest : public EmbedderTest {
18 protected:
SetUp()19 void SetUp() override {
20 EmbedderTest::SetUp();
21 CreateAndInitializeFormComboboxPDF();
22 }
23
TearDown()24 void TearDown() override {
25 UnloadPage(GetPage());
26 EmbedderTest::TearDown();
27 }
28
CreateAndInitializeFormComboboxPDF()29 void CreateAndInitializeFormComboboxPDF() {
30 EXPECT_TRUE(OpenDocument("combobox_form.pdf"));
31 m_page = LoadPage(0);
32 ASSERT_TRUE(m_page);
33
34 m_pFormFillEnv =
35 CPDFSDKFormFillEnvironmentFromFPDFFormHandle(form_handle());
36 CPDFSDK_AnnotIterator iter(m_pFormFillEnv->GetPageView(0),
37 CPDF_Annot::Subtype::WIDGET);
38
39 // User editable combobox.
40 m_pAnnotEditable = iter.GetFirstAnnot();
41 ASSERT_TRUE(m_pAnnotEditable);
42 ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnotEditable->GetAnnotSubtype());
43
44 // Normal combobox with pre-selected value.
45 m_pAnnotNormal = iter.GetNextAnnot(m_pAnnotEditable);
46 ASSERT_TRUE(m_pAnnotNormal);
47 ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnotNormal->GetAnnotSubtype());
48
49 // Read-only combobox.
50 CPDFSDK_Annot* pAnnotReadOnly = iter.GetNextAnnot(m_pAnnotNormal);
51 CPDFSDK_Annot* pLastAnnot = iter.GetLastAnnot();
52 ASSERT_EQ(pAnnotReadOnly, pLastAnnot);
53 }
54
FormFillerAndWindowSetup(CPDFSDK_Annot * pAnnotCombobox)55 void FormFillerAndWindowSetup(CPDFSDK_Annot* pAnnotCombobox) {
56 CFFL_InteractiveFormFiller* pInteractiveFormFiller =
57 m_pFormFillEnv->GetInteractiveFormFiller();
58 {
59 ObservedPtr<CPDFSDK_Annot> pObserved(pAnnotCombobox);
60 EXPECT_TRUE(pInteractiveFormFiller->OnSetFocus(&pObserved, 0));
61 }
62
63 m_pFormFiller =
64 pInteractiveFormFiller->GetFormFillerForTesting(pAnnotCombobox);
65 ASSERT_TRUE(m_pFormFiller);
66
67 CPWL_Wnd* pWindow =
68 m_pFormFiller->GetPWLWindow(m_pFormFillEnv->GetPageView(0), false);
69 ASSERT_TRUE(pWindow);
70 m_pComboBox = static_cast<CPWL_ComboBox*>(pWindow);
71 }
72
TypeTextIntoTextField(int num_chars)73 void TypeTextIntoTextField(int num_chars) {
74 // Type text starting with 'A' to as many chars as specified by |num_chars|.
75 for (int i = 0; i < num_chars; ++i) {
76 EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(),
77 i + 'A', 0));
78 }
79 }
80
GetPage() const81 FPDF_PAGE GetPage() const { return m_page; }
GetCPWLComboBox() const82 CPWL_ComboBox* GetCPWLComboBox() const { return m_pComboBox; }
GetCFFLFormFiller() const83 CFFL_FormFiller* GetCFFLFormFiller() const { return m_pFormFiller; }
GetCPDFSDKAnnotNormal() const84 CPDFSDK_Annot* GetCPDFSDKAnnotNormal() const { return m_pAnnotNormal; }
GetCPDFSDKAnnotUserEditable() const85 CPDFSDK_Annot* GetCPDFSDKAnnotUserEditable() const {
86 return m_pAnnotEditable;
87 }
GetCPDFSDKFormFillEnv() const88 CPDFSDK_FormFillEnvironment* GetCPDFSDKFormFillEnv() const {
89 return m_pFormFillEnv;
90 }
91
92 private:
93 FPDF_PAGE m_page;
94 CPWL_ComboBox* m_pComboBox;
95 CFFL_FormFiller* m_pFormFiller;
96 CPDFSDK_Annot* m_pAnnotNormal;
97 CPDFSDK_Annot* m_pAnnotEditable;
98 CPDFSDK_FormFillEnvironment* m_pFormFillEnv;
99 };
100
TEST_F(CPWLComboBoxEditEmbedderTest,GetSelectedTextEmptyAndBasicNormal)101 TEST_F(CPWLComboBoxEditEmbedderTest, GetSelectedTextEmptyAndBasicNormal) {
102 FormFillerAndWindowSetup(GetCPDFSDKAnnotNormal());
103
104 // Automatically pre-filled with "Banana".
105 EXPECT_FALSE(GetCPWLComboBox()->GetText().IsEmpty());
106 EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetText().c_str());
107
108 // Check that selection is intially empty, then select entire word.
109 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
110 GetCPWLComboBox()->SetSelectText();
111 EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetSelectedText().c_str());
112
113 // Select other options.
114 GetCPWLComboBox()->SetSelect(0);
115 EXPECT_STREQ(L"Apple", GetCPWLComboBox()->GetSelectedText().c_str());
116 GetCPWLComboBox()->SetSelect(2);
117 EXPECT_STREQ(L"Cherry", GetCPWLComboBox()->GetSelectedText().c_str());
118
119 // Verify that combobox text cannot be edited.
120 EXPECT_FALSE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotNormal(), 'a', 0));
121 }
122
TEST_F(CPWLComboBoxEditEmbedderTest,GetSelectedTextFragmentsNormal)123 TEST_F(CPWLComboBoxEditEmbedderTest, GetSelectedTextFragmentsNormal) {
124 FormFillerAndWindowSetup(GetCPDFSDKAnnotNormal());
125 EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetText().c_str());
126
127 GetCPWLComboBox()->SetEditSelection(0, 0);
128 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
129
130 GetCPWLComboBox()->SetEditSelection(0, 1);
131 EXPECT_STREQ(L"B", GetCPWLComboBox()->GetSelectedText().c_str());
132
133 GetCPWLComboBox()->SetEditSelection(0, -1);
134 EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetSelectedText().c_str());
135
136 GetCPWLComboBox()->SetEditSelection(-8, -1);
137 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
138
139 GetCPWLComboBox()->SetEditSelection(4, 1);
140 EXPECT_STREQ(L"ana", GetCPWLComboBox()->GetSelectedText().c_str());
141
142 GetCPWLComboBox()->SetEditSelection(1, 4);
143 EXPECT_STREQ(L"ana", GetCPWLComboBox()->GetSelectedText().c_str());
144
145 GetCPWLComboBox()->SetEditSelection(5, 6);
146 EXPECT_STREQ(L"a", GetCPWLComboBox()->GetSelectedText().c_str());
147 }
148
TEST_F(CPWLComboBoxEditEmbedderTest,GetSelectedTextEmptyAndBasicEditable)149 TEST_F(CPWLComboBoxEditEmbedderTest, GetSelectedTextEmptyAndBasicEditable) {
150 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
151 EXPECT_TRUE(GetCPWLComboBox()->GetText().IsEmpty());
152
153 // Check selection is intially empty, then select a provided option.
154 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
155 GetCPWLComboBox()->SetSelect(0);
156 GetCPWLComboBox()->SetSelectText();
157 EXPECT_STREQ(L"Foo", GetCPWLComboBox()->GetSelectedText().c_str());
158
159 // Select another option and then select last char of that option.
160 GetCPWLComboBox()->SetSelect(1);
161 EXPECT_STREQ(L"Bar", GetCPWLComboBox()->GetSelectedText().c_str());
162 GetCPWLComboBox()->SetEditSelection(2, 3);
163 EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str());
164
165 // Type into editable combobox text field and select new text.
166 EXPECT_TRUE(
167 GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'a', 0));
168 EXPECT_TRUE(
169 GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'b', 0));
170 EXPECT_TRUE(
171 GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'c', 0));
172
173 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
174 GetCPWLComboBox()->SetEditSelection(0, 5);
175 EXPECT_STREQ(L"Baabc", GetCPWLComboBox()->GetSelectedText().c_str());
176 }
177
TEST_F(CPWLComboBoxEditEmbedderTest,GetSelectedTextFragmentsEditable)178 TEST_F(CPWLComboBoxEditEmbedderTest, GetSelectedTextFragmentsEditable) {
179 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
180 TypeTextIntoTextField(50);
181
182 GetCPWLComboBox()->SetEditSelection(0, 0);
183 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
184
185 GetCPWLComboBox()->SetEditSelection(0, 1);
186 EXPECT_STREQ(L"A", GetCPWLComboBox()->GetSelectedText().c_str());
187
188 GetCPWLComboBox()->SetEditSelection(0, -1);
189 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
190 GetCPWLComboBox()->GetSelectedText().c_str());
191
192 GetCPWLComboBox()->SetEditSelection(-8, -1);
193 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
194
195 GetCPWLComboBox()->SetEditSelection(23, 12);
196 EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str());
197
198 GetCPWLComboBox()->SetEditSelection(12, 23);
199 EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str());
200
201 GetCPWLComboBox()->SetEditSelection(49, 50);
202 EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str());
203
204 GetCPWLComboBox()->SetEditSelection(49, 55);
205 EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str());
206 }
207
TEST_F(CPWLComboBoxEditEmbedderTest,DeleteEntireTextSelection)208 TEST_F(CPWLComboBoxEditEmbedderTest, DeleteEntireTextSelection) {
209 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
210 TypeTextIntoTextField(50);
211
212 GetCPWLComboBox()->SetEditSelection(0, -1);
213 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
214 GetCPWLComboBox()->GetSelectedText().c_str());
215
216 GetCPWLComboBox()->ReplaceSelection(L"");
217 EXPECT_TRUE(GetCPWLComboBox()->GetText().IsEmpty());
218 }
219
TEST_F(CPWLComboBoxEditEmbedderTest,DeleteTextSelectionMiddle)220 TEST_F(CPWLComboBoxEditEmbedderTest, DeleteTextSelectionMiddle) {
221 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
222 TypeTextIntoTextField(50);
223
224 GetCPWLComboBox()->SetEditSelection(12, 23);
225 EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str());
226
227 GetCPWLComboBox()->ReplaceSelection(L"");
228 EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr",
229 GetCPWLComboBox()->GetText().c_str());
230 }
231
TEST_F(CPWLComboBoxEditEmbedderTest,DeleteTextSelectionLeft)232 TEST_F(CPWLComboBoxEditEmbedderTest, DeleteTextSelectionLeft) {
233 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
234 TypeTextIntoTextField(50);
235
236 GetCPWLComboBox()->SetEditSelection(0, 5);
237 EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str());
238
239 GetCPWLComboBox()->ReplaceSelection(L"");
240 EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
241 GetCPWLComboBox()->GetText().c_str());
242 }
243
TEST_F(CPWLComboBoxEditEmbedderTest,DeleteTextSelectionRight)244 TEST_F(CPWLComboBoxEditEmbedderTest, DeleteTextSelectionRight) {
245 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
246 TypeTextIntoTextField(50);
247
248 GetCPWLComboBox()->SetEditSelection(45, 50);
249 EXPECT_STREQ(L"nopqr", GetCPWLComboBox()->GetSelectedText().c_str());
250
251 GetCPWLComboBox()->ReplaceSelection(L"");
252 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm",
253 GetCPWLComboBox()->GetText().c_str());
254 }
255
TEST_F(CPWLComboBoxEditEmbedderTest,DeleteEmptyTextSelection)256 TEST_F(CPWLComboBoxEditEmbedderTest, DeleteEmptyTextSelection) {
257 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
258 TypeTextIntoTextField(50);
259
260 GetCPWLComboBox()->ReplaceSelection(L"");
261 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
262 GetCPWLComboBox()->GetText().c_str());
263 }
264
TEST_F(CPWLComboBoxEditEmbedderTest,InsertTextInEmptyEditableComboBox)265 TEST_F(CPWLComboBoxEditEmbedderTest, InsertTextInEmptyEditableComboBox) {
266 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
267 GetCPWLComboBox()->ReplaceSelection(L"Hello");
268 EXPECT_STREQ(L"Hello", GetCPWLComboBox()->GetText().c_str());
269 }
270
TEST_F(CPWLComboBoxEditEmbedderTest,InsertTextInPopulatedEditableComboBoxLeft)271 TEST_F(CPWLComboBoxEditEmbedderTest,
272 InsertTextInPopulatedEditableComboBoxLeft) {
273 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
274 TypeTextIntoTextField(10);
275
276 // Move cursor to beginning of user-editable combobox text field.
277 EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(FWL_VKEY_Home, 0));
278
279 GetCPWLComboBox()->ReplaceSelection(L"Hello");
280 EXPECT_STREQ(L"HelloABCDEFGHIJ", GetCPWLComboBox()->GetText().c_str());
281 }
282
TEST_F(CPWLComboBoxEditEmbedderTest,InsertTextInPopulatedEditableComboBoxMiddle)283 TEST_F(CPWLComboBoxEditEmbedderTest,
284 InsertTextInPopulatedEditableComboBoxMiddle) {
285 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
286 TypeTextIntoTextField(10);
287
288 // Move cursor to middle of user-editable combobox text field.
289 for (int i = 0; i < 5; ++i) {
290 EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(FWL_VKEY_Left, 0));
291 }
292
293 GetCPWLComboBox()->ReplaceSelection(L"Hello");
294 EXPECT_STREQ(L"ABCDEHelloFGHIJ", GetCPWLComboBox()->GetText().c_str());
295 }
296
TEST_F(CPWLComboBoxEditEmbedderTest,InsertTextInPopulatedEditableComboBoxRight)297 TEST_F(CPWLComboBoxEditEmbedderTest,
298 InsertTextInPopulatedEditableComboBoxRight) {
299 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
300 TypeTextIntoTextField(10);
301
302 GetCPWLComboBox()->ReplaceSelection(L"Hello");
303 EXPECT_STREQ(L"ABCDEFGHIJHello", GetCPWLComboBox()->GetText().c_str());
304 }
305
TEST_F(CPWLComboBoxEditEmbedderTest,InsertTextAndReplaceSelectionInPopulatedEditableComboBoxWhole)306 TEST_F(CPWLComboBoxEditEmbedderTest,
307 InsertTextAndReplaceSelectionInPopulatedEditableComboBoxWhole) {
308 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
309 TypeTextIntoTextField(10);
310
311 GetCPWLComboBox()->SetEditSelection(0, -1);
312 EXPECT_STREQ(L"ABCDEFGHIJ", GetCPWLComboBox()->GetSelectedText().c_str());
313 GetCPWLComboBox()->ReplaceSelection(L"Hello");
314 EXPECT_STREQ(L"Hello", GetCPWLComboBox()->GetText().c_str());
315 }
316
TEST_F(CPWLComboBoxEditEmbedderTest,InsertTextAndReplaceSelectionInPopulatedEditableComboBoxLeft)317 TEST_F(CPWLComboBoxEditEmbedderTest,
318 InsertTextAndReplaceSelectionInPopulatedEditableComboBoxLeft) {
319 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
320 TypeTextIntoTextField(10);
321
322 GetCPWLComboBox()->SetEditSelection(0, 5);
323 EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str());
324 GetCPWLComboBox()->ReplaceSelection(L"Hello");
325 EXPECT_STREQ(L"HelloFGHIJ", GetCPWLComboBox()->GetText().c_str());
326 }
327
TEST_F(CPWLComboBoxEditEmbedderTest,InsertTextAndReplaceSelectionInPopulatedEditableComboBoxMiddle)328 TEST_F(CPWLComboBoxEditEmbedderTest,
329 InsertTextAndReplaceSelectionInPopulatedEditableComboBoxMiddle) {
330 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
331 TypeTextIntoTextField(10);
332
333 GetCPWLComboBox()->SetEditSelection(2, 7);
334 EXPECT_STREQ(L"CDEFG", GetCPWLComboBox()->GetSelectedText().c_str());
335 GetCPWLComboBox()->ReplaceSelection(L"Hello");
336 EXPECT_STREQ(L"ABHelloHIJ", GetCPWLComboBox()->GetText().c_str());
337 }
338
TEST_F(CPWLComboBoxEditEmbedderTest,InsertTextAndReplaceSelectionInPopulatedEditableComboBoxRight)339 TEST_F(CPWLComboBoxEditEmbedderTest,
340 InsertTextAndReplaceSelectionInPopulatedEditableComboBoxRight) {
341 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
342 TypeTextIntoTextField(10);
343
344 GetCPWLComboBox()->SetEditSelection(5, 10);
345 EXPECT_STREQ(L"FGHIJ", GetCPWLComboBox()->GetSelectedText().c_str());
346 GetCPWLComboBox()->ReplaceSelection(L"Hello");
347 EXPECT_STREQ(L"ABCDEHello", GetCPWLComboBox()->GetText().c_str());
348 }
349