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/cba_annotiterator.h" 6 #include "fpdfsdk/cpdfsdk_annot.h" 7 #include "fpdfsdk/cpdfsdk_formfillenvironment.h" 8 #include "fpdfsdk/formfiller/cffl_formfiller.h" 9 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" 10 #include "fpdfsdk/pwl/cpwl_wnd.h" 11 #include "testing/embedder_test.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 class CPWLEditEmbeddertest : public EmbedderTest { 15 protected: 16 void SetUp() override { 17 EmbedderTest::SetUp(); 18 CreateAndInitializeFormPDF(); 19 } 20 21 void TearDown() override { 22 UnloadPage(GetPage()); 23 EmbedderTest::TearDown(); 24 } 25 26 void CreateAndInitializeFormPDF() { 27 EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); 28 m_page = LoadPage(0); 29 ASSERT_TRUE(m_page); 30 31 m_pFormFillEnv = static_cast<CPDFSDK_FormFillEnvironment*>(form_handle()); 32 CBA_AnnotIterator iter(m_pFormFillEnv->GetPageView(0), 33 CPDF_Annot::Subtype::WIDGET); 34 // Normal text field. 35 m_pAnnot = iter.GetFirstAnnot(); 36 ASSERT_TRUE(m_pAnnot); 37 ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnot->GetAnnotSubtype()); 38 39 // Read-only text field. 40 CPDFSDK_Annot* pAnnotReadOnly = iter.GetNextAnnot(m_pAnnot); 41 42 // Pre-filled text field with char limit of 10. 43 m_pAnnotCharLimit = iter.GetNextAnnot(pAnnotReadOnly); 44 ASSERT_TRUE(m_pAnnotCharLimit); 45 ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, 46 m_pAnnotCharLimit->GetAnnotSubtype()); 47 CPDFSDK_Annot* pLastAnnot = iter.GetLastAnnot(); 48 ASSERT_EQ(m_pAnnotCharLimit, pLastAnnot); 49 } 50 51 void FormFillerAndWindowSetup(CPDFSDK_Annot* pAnnotTextField) { 52 CFFL_InteractiveFormFiller* pInteractiveFormFiller = 53 m_pFormFillEnv->GetInteractiveFormFiller(); 54 { 55 CPDFSDK_Annot::ObservedPtr pObserved(pAnnotTextField); 56 EXPECT_TRUE(pInteractiveFormFiller->OnSetFocus(&pObserved, 0)); 57 } 58 59 m_pFormFiller = 60 pInteractiveFormFiller->GetFormFiller(pAnnotTextField, false); 61 ASSERT_TRUE(m_pFormFiller); 62 63 CPWL_Wnd* pWindow = 64 m_pFormFiller->GetPDFWindow(m_pFormFillEnv->GetPageView(0), false); 65 ASSERT_TRUE(pWindow); 66 ASSERT_EQ(PWL_CLASSNAME_EDIT, pWindow->GetClassName()); 67 68 m_pEdit = static_cast<CPWL_Edit*>(pWindow); 69 } 70 71 void TypeTextIntoTextField(int num_chars) { 72 // Type text starting with 'A' to as many chars as specified by |num_chars|. 73 for (int i = 0; i < num_chars; ++i) { 74 EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); 75 } 76 } 77 78 FPDF_PAGE GetPage() { return m_page; } 79 CPWL_Edit* GetCPWLEdit() { return m_pEdit; } 80 CFFL_FormFiller* GetCFFLFormFiller() { return m_pFormFiller; } 81 CPDFSDK_Annot* GetCPDFSDKAnnot() { return m_pAnnot; } 82 CPDFSDK_Annot* GetCPDFSDKAnnotCharLimit() { return m_pAnnotCharLimit; } 83 84 private: 85 FPDF_PAGE m_page; 86 CPWL_Edit* m_pEdit; 87 CFFL_FormFiller* m_pFormFiller; 88 CPDFSDK_Annot* m_pAnnot; 89 CPDFSDK_Annot* m_pAnnotCharLimit; 90 CPDFSDK_FormFillEnvironment* m_pFormFillEnv; 91 }; 92 93 TEST_F(CPWLEditEmbeddertest, TypeText) { 94 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 95 EXPECT_TRUE(GetCPWLEdit()->GetText().IsEmpty()); 96 EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'a', 0)); 97 EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'b', 0)); 98 EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'c', 0)); 99 100 EXPECT_STREQ(L"abc", GetCPWLEdit()->GetText().c_str()); 101 } 102 103 TEST_F(CPWLEditEmbeddertest, GetSelectedTextEmptyAndBasic) { 104 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 105 // Attempt to set selection before text has been typed to test that 106 // selection is identified as empty. 107 // 108 // Select from character index [0, 3) within form text field. 109 GetCPWLEdit()->SetSelection(0, 3); 110 EXPECT_TRUE(GetCPWLEdit()->GetSelectedText().IsEmpty()); 111 112 EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'a', 0)); 113 EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'b', 0)); 114 EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'c', 0)); 115 GetCPWLEdit()->SetSelection(0, 2); 116 117 EXPECT_STREQ(L"ab", GetCPWLEdit()->GetSelectedText().c_str()); 118 } 119 120 TEST_F(CPWLEditEmbeddertest, GetSelectedTextFragments) { 121 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 122 TypeTextIntoTextField(50); 123 124 GetCPWLEdit()->SetSelection(0, 0); 125 EXPECT_TRUE(GetCPWLEdit()->GetSelectedText().IsEmpty()); 126 127 GetCPWLEdit()->SetSelection(0, 1); 128 EXPECT_STREQ(L"A", GetCPWLEdit()->GetSelectedText().c_str()); 129 130 GetCPWLEdit()->SetSelection(0, -1); 131 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", 132 GetCPWLEdit()->GetSelectedText().c_str()); 133 134 GetCPWLEdit()->SetSelection(-8, -1); 135 EXPECT_TRUE(GetCPWLEdit()->GetSelectedText().IsEmpty()); 136 137 GetCPWLEdit()->SetSelection(23, 12); 138 EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str()); 139 140 GetCPWLEdit()->SetSelection(12, 23); 141 EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str()); 142 143 GetCPWLEdit()->SetSelection(49, 50); 144 EXPECT_STREQ(L"r", GetCPWLEdit()->GetSelectedText().c_str()); 145 146 GetCPWLEdit()->SetSelection(49, 55); 147 EXPECT_STREQ(L"r", GetCPWLEdit()->GetSelectedText().c_str()); 148 } 149 150 TEST_F(CPWLEditEmbeddertest, DeleteEntireTextSelection) { 151 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 152 TypeTextIntoTextField(50); 153 154 GetCPWLEdit()->SetSelection(0, -1); 155 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", 156 GetCPWLEdit()->GetSelectedText().c_str()); 157 158 GetCPWLEdit()->ReplaceSelection(L""); 159 EXPECT_TRUE(GetCPWLEdit()->GetText().IsEmpty()); 160 } 161 162 TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionMiddle) { 163 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 164 TypeTextIntoTextField(50); 165 166 GetCPWLEdit()->SetSelection(12, 23); 167 EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str()); 168 169 GetCPWLEdit()->ReplaceSelection(L""); 170 EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr", 171 GetCPWLEdit()->GetText().c_str()); 172 } 173 174 TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionLeft) { 175 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 176 TypeTextIntoTextField(50); 177 178 GetCPWLEdit()->SetSelection(0, 5); 179 EXPECT_STREQ(L"ABCDE", GetCPWLEdit()->GetSelectedText().c_str()); 180 181 GetCPWLEdit()->ReplaceSelection(L""); 182 EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", 183 GetCPWLEdit()->GetText().c_str()); 184 } 185 186 TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionRight) { 187 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 188 TypeTextIntoTextField(50); 189 190 GetCPWLEdit()->SetSelection(45, 50); 191 EXPECT_STREQ(L"nopqr", GetCPWLEdit()->GetSelectedText().c_str()); 192 193 GetCPWLEdit()->ReplaceSelection(L""); 194 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm", 195 GetCPWLEdit()->GetText().c_str()); 196 } 197 198 TEST_F(CPWLEditEmbeddertest, DeleteEmptyTextSelection) { 199 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 200 TypeTextIntoTextField(50); 201 202 GetCPWLEdit()->ReplaceSelection(L""); 203 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", 204 GetCPWLEdit()->GetText().c_str()); 205 } 206 207 TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyTextField) { 208 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 209 GetCPWLEdit()->ReplaceSelection(L"Hello"); 210 EXPECT_STREQ(L"Hello", GetCPWLEdit()->GetText().c_str()); 211 } 212 213 TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldLeft) { 214 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 215 TypeTextIntoTextField(10); 216 217 // Move cursor to beginning of text field. 218 EXPECT_TRUE( 219 GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnot(), FWL_VKEY_Home, 0)); 220 221 GetCPWLEdit()->ReplaceSelection(L"Hello"); 222 EXPECT_STREQ(L"HelloABCDEFGHIJ", GetCPWLEdit()->GetText().c_str()); 223 } 224 225 TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldMiddle) { 226 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 227 TypeTextIntoTextField(10); 228 229 // Move cursor to middle of text field. 230 for (int i = 0; i < 5; ++i) { 231 EXPECT_TRUE( 232 GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnot(), FWL_VKEY_Left, 0)); 233 } 234 235 GetCPWLEdit()->ReplaceSelection(L"Hello"); 236 EXPECT_STREQ(L"ABCDEHelloFGHIJ", GetCPWLEdit()->GetText().c_str()); 237 } 238 239 TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldRight) { 240 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 241 TypeTextIntoTextField(10); 242 243 GetCPWLEdit()->ReplaceSelection(L"Hello"); 244 EXPECT_STREQ(L"ABCDEFGHIJHello", GetCPWLEdit()->GetText().c_str()); 245 } 246 247 TEST_F(CPWLEditEmbeddertest, 248 InsertTextAndReplaceSelectionInPopulatedTextFieldWhole) { 249 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 250 TypeTextIntoTextField(10); 251 252 GetCPWLEdit()->SetSelection(0, -1); 253 EXPECT_STREQ(L"ABCDEFGHIJ", GetCPWLEdit()->GetSelectedText().c_str()); 254 GetCPWLEdit()->ReplaceSelection(L"Hello"); 255 EXPECT_STREQ(L"Hello", GetCPWLEdit()->GetText().c_str()); 256 } 257 258 TEST_F(CPWLEditEmbeddertest, 259 InsertTextAndReplaceSelectionInPopulatedTextFieldLeft) { 260 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 261 TypeTextIntoTextField(10); 262 263 GetCPWLEdit()->SetSelection(0, 5); 264 EXPECT_STREQ(L"ABCDE", GetCPWLEdit()->GetSelectedText().c_str()); 265 GetCPWLEdit()->ReplaceSelection(L"Hello"); 266 EXPECT_STREQ(L"HelloFGHIJ", GetCPWLEdit()->GetText().c_str()); 267 } 268 269 TEST_F(CPWLEditEmbeddertest, 270 InsertTextAndReplaceSelectionInPopulatedTextFieldMiddle) { 271 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 272 TypeTextIntoTextField(10); 273 274 GetCPWLEdit()->SetSelection(2, 7); 275 EXPECT_STREQ(L"CDEFG", GetCPWLEdit()->GetSelectedText().c_str()); 276 GetCPWLEdit()->ReplaceSelection(L"Hello"); 277 EXPECT_STREQ(L"ABHelloHIJ", GetCPWLEdit()->GetText().c_str()); 278 } 279 280 TEST_F(CPWLEditEmbeddertest, 281 InsertTextAndReplaceSelectionInPopulatedTextFieldRight) { 282 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 283 TypeTextIntoTextField(10); 284 285 GetCPWLEdit()->SetSelection(5, 10); 286 EXPECT_STREQ(L"FGHIJ", GetCPWLEdit()->GetSelectedText().c_str()); 287 GetCPWLEdit()->ReplaceSelection(L"Hello"); 288 EXPECT_STREQ(L"ABCDEHello", GetCPWLEdit()->GetText().c_str()); 289 } 290 291 TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyCharLimitTextFieldOverflow) { 292 FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); 293 GetCPWLEdit()->SetSelection(0, -1); 294 EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str()); 295 GetCPWLEdit()->ReplaceSelection(L""); 296 297 GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); 298 EXPECT_STREQ(L"Hippopotam", GetCPWLEdit()->GetText().c_str()); 299 } 300 301 TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyCharLimitTextFieldFit) { 302 FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); 303 GetCPWLEdit()->SetSelection(0, -1); 304 EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str()); 305 GetCPWLEdit()->ReplaceSelection(L""); 306 307 GetCPWLEdit()->ReplaceSelection(L"Zebra"); 308 EXPECT_STREQ(L"Zebra", GetCPWLEdit()->GetText().c_str()); 309 } 310 311 TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldLeft) { 312 FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); 313 GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); 314 EXPECT_STREQ(L"HiElephant", GetCPWLEdit()->GetText().c_str()); 315 } 316 317 TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldMiddle) { 318 FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); 319 // Move cursor to middle of text field. 320 for (int i = 0; i < 5; ++i) { 321 EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotCharLimit(), 322 FWL_VKEY_Right, 0)); 323 } 324 325 GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); 326 EXPECT_STREQ(L"ElephHiant", GetCPWLEdit()->GetText().c_str()); 327 } 328 329 TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldRight) { 330 FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); 331 // Move cursor to end of text field. 332 EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotCharLimit(), 333 FWL_VKEY_End, 0)); 334 335 GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); 336 EXPECT_STREQ(L"ElephantHi", GetCPWLEdit()->GetText().c_str()); 337 } 338 339 TEST_F(CPWLEditEmbeddertest, 340 InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldWhole) { 341 FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); 342 GetCPWLEdit()->SetSelection(0, -1); 343 EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str()); 344 GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); 345 EXPECT_STREQ(L"Hippopotam", GetCPWLEdit()->GetText().c_str()); 346 } 347 348 TEST_F(CPWLEditEmbeddertest, 349 InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldLeft) { 350 FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); 351 GetCPWLEdit()->SetSelection(0, 4); 352 EXPECT_STREQ(L"Elep", GetCPWLEdit()->GetSelectedText().c_str()); 353 GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); 354 EXPECT_STREQ(L"Hippophant", GetCPWLEdit()->GetText().c_str()); 355 } 356 357 TEST_F(CPWLEditEmbeddertest, 358 InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldMiddle) { 359 FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); 360 GetCPWLEdit()->SetSelection(2, 6); 361 EXPECT_STREQ(L"epha", GetCPWLEdit()->GetSelectedText().c_str()); 362 GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); 363 EXPECT_STREQ(L"ElHippopnt", GetCPWLEdit()->GetText().c_str()); 364 } 365 366 TEST_F(CPWLEditEmbeddertest, 367 InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldRight) { 368 FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); 369 GetCPWLEdit()->SetSelection(4, 8); 370 EXPECT_STREQ(L"hant", GetCPWLEdit()->GetSelectedText().c_str()); 371 GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); 372 EXPECT_STREQ(L"ElepHippop", GetCPWLEdit()->GetText().c_str()); 373 } 374 375 TEST_F(CPWLEditEmbeddertest, SetTextWithEndCarriageFeed) { 376 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 377 GetCPWLEdit()->SetText(L"Foo\r"); 378 EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str()); 379 } 380 381 TEST_F(CPWLEditEmbeddertest, SetTextWithEndNewline) { 382 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 383 GetCPWLEdit()->SetText(L"Foo\n"); 384 EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str()); 385 } 386 387 TEST_F(CPWLEditEmbeddertest, SetTextWithEndCarriageFeedAndNewLine) { 388 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 389 GetCPWLEdit()->SetText(L"Foo\r\n"); 390 EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str()); 391 } 392 393 TEST_F(CPWLEditEmbeddertest, SetTextWithEndNewLineAndCarriageFeed) { 394 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 395 GetCPWLEdit()->SetText(L"Foo\n\r"); 396 EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str()); 397 } 398 399 TEST_F(CPWLEditEmbeddertest, SetTextWithBodyCarriageFeed) { 400 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 401 GetCPWLEdit()->SetText(L"Foo\rBar"); 402 EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str()); 403 } 404 405 TEST_F(CPWLEditEmbeddertest, SetTextWithBodyNewline) { 406 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 407 GetCPWLEdit()->SetText(L"Foo\nBar"); 408 EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str()); 409 } 410 411 TEST_F(CPWLEditEmbeddertest, SetTextWithBodyCarriageFeedAndNewLine) { 412 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 413 GetCPWLEdit()->SetText(L"Foo\r\nBar"); 414 EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str()); 415 } 416 417 TEST_F(CPWLEditEmbeddertest, SetTextWithBodyNewLineAndCarriageFeed) { 418 FormFillerAndWindowSetup(GetCPDFSDKAnnot()); 419 GetCPWLEdit()->SetText(L"Foo\n\rBar"); 420 EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str()); 421 } 422