Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 PDFium Authors. All rights reserved. | 1 // Copyright 2016 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include "fpdfsdk/cpdfsdk_formfillenvironment.h" | 7 #include "fpdfsdk/cpdfsdk_formfillenvironment.h" |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| 11 #include "core/fpdfapi/parser/cpdf_array.h" | |
| 12 #include "core/fpdfdoc/cpdf_docjsactions.h" | |
| 11 #include "fpdfsdk/cpdfsdk_annothandlermgr.h" | 13 #include "fpdfsdk/cpdfsdk_annothandlermgr.h" |
| 12 #include "fpdfsdk/cpdfsdk_document.h" | 14 #include "fpdfsdk/cpdfsdk_interform.h" |
| 15 #include "fpdfsdk/cpdfsdk_pageview.h" | |
| 16 #include "fpdfsdk/cpdfsdk_widget.h" | |
| 13 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" | 17 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" |
| 14 #include "fpdfsdk/fsdk_actionhandler.h" | 18 #include "fpdfsdk/fsdk_actionhandler.h" |
| 15 #include "fpdfsdk/javascript/ijs_runtime.h" | 19 #include "fpdfsdk/javascript/ijs_runtime.h" |
| 16 #include "third_party/base/ptr_util.h" | 20 #include "third_party/base/ptr_util.h" |
| 17 | 21 |
| 18 #ifdef PDF_ENABLE_XFA | 22 #ifdef PDF_ENABLE_XFA |
| 19 #include "fpdfsdk/fpdfxfa/cpdfxfa_app.h" | 23 #include "fpdfsdk/fpdfxfa/cpdfxfa_app.h" |
| 20 #endif // PDF_ENABLE_XFA | 24 #endif // PDF_ENABLE_XFA |
| 21 | 25 |
| 22 namespace { | 26 namespace { |
| 23 | 27 |
| 24 // NOTE: |bsUTF16LE| must outlive the use of the result. Care must be taken | 28 // NOTE: |bsUTF16LE| must outlive the use of the result. Care must be taken |
| 25 // since modifying the result would impact |bsUTF16LE|. | 29 // since modifying the result would impact |bsUTF16LE|. |
| 26 FPDF_WIDESTRING AsFPDFWideString(CFX_ByteString* bsUTF16LE) { | 30 FPDF_WIDESTRING AsFPDFWideString(CFX_ByteString* bsUTF16LE) { |
| 27 return reinterpret_cast<FPDF_WIDESTRING>( | 31 return reinterpret_cast<FPDF_WIDESTRING>( |
| 28 bsUTF16LE->GetBuffer(bsUTF16LE->GetLength())); | 32 bsUTF16LE->GetBuffer(bsUTF16LE->GetLength())); |
| 29 } | 33 } |
| 30 | 34 |
| 31 } // namespace | 35 } // namespace |
| 32 | 36 |
| 33 CPDFSDK_FormFillEnvironment::CPDFSDK_FormFillEnvironment( | 37 CPDFSDK_FormFillEnvironment::CPDFSDK_FormFillEnvironment( |
| 34 UnderlyingDocumentType* pDoc, | 38 UnderlyingDocumentType* pDoc, |
| 35 FPDF_FORMFILLINFO* pFFinfo) | 39 FPDF_FORMFILLINFO* pFFinfo) |
| 36 : m_pInfo(pFFinfo), | 40 : m_pInfo(pFFinfo), |
| 37 m_pSDKDoc(new CPDFSDK_Document(pDoc, this)), | |
| 38 m_pUnderlyingDoc(pDoc), | 41 m_pUnderlyingDoc(pDoc), |
| 39 m_pSysHandler(new CFX_SystemHandler(this)) {} | 42 m_pSysHandler(new CFX_SystemHandler(this)), |
| 43 m_bChangeMask(FALSE), | |
| 44 m_bBeingDestroyed(FALSE) {} | |
| 40 | 45 |
| 41 CPDFSDK_FormFillEnvironment::~CPDFSDK_FormFillEnvironment() { | 46 CPDFSDK_FormFillEnvironment::~CPDFSDK_FormFillEnvironment() { |
| 47 m_bBeingDestroyed = TRUE; | |
| 48 | |
| 49 ClearAllFocusedAnnots(); | |
| 50 for (auto& it : m_pageMap) | |
|
Tom Sepez
2016/10/12 18:52:59
nit: map of unique_ptrs (keep .clear() if order im
dsinclair
2016/10/12 19:44:29
Done.
| |
| 51 delete it.second; | |
| 52 m_pageMap.clear(); | |
| 53 | |
| 42 // |m_pAnnotHandlerMgr| will try to access |m_pFormFiller| | 54 // |m_pAnnotHandlerMgr| will try to access |m_pFormFiller| |
| 43 // when it cleans up. So, we must make sure it is cleaned up before | 55 // when it cleans up. So, we must make sure it is cleaned up before |
| 44 // |m_pFormFiller|. | 56 // |m_pFormFiller|. |
| 45 m_pAnnotHandlerMgr.reset(); | 57 m_pAnnotHandlerMgr.reset(); |
| 46 | 58 |
| 47 // Must destroy the |m_pFormFiller| before the environment (|this|) | 59 // Must destroy the |m_pFormFiller| before the environment (|this|) |
| 48 // because any created form widgets hold a pointer to the environment. | 60 // because any created form widgets hold a pointer to the environment. |
| 49 // Those widgets may call things like KillTimer() as they are shutdown. | 61 // Those widgets may call things like KillTimer() as they are shutdown. |
| 50 m_pFormFiller.reset(); | 62 m_pFormFiller.reset(); |
| 51 | 63 |
| (...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 555 delete[] pbuff; | 567 delete[] pbuff; |
| 556 return wsRet; | 568 return wsRet; |
| 557 } | 569 } |
| 558 | 570 |
| 559 void CPDFSDK_FormFillEnvironment::PageEvent(int iPageCount, | 571 void CPDFSDK_FormFillEnvironment::PageEvent(int iPageCount, |
| 560 uint32_t dwEventType) const { | 572 uint32_t dwEventType) const { |
| 561 if (m_pInfo && m_pInfo->FFI_PageEvent) | 573 if (m_pInfo && m_pInfo->FFI_PageEvent) |
| 562 m_pInfo->FFI_PageEvent(m_pInfo, iPageCount, dwEventType); | 574 m_pInfo->FFI_PageEvent(m_pInfo, iPageCount, dwEventType); |
| 563 } | 575 } |
| 564 #endif // PDF_ENABLE_XFA | 576 #endif // PDF_ENABLE_XFA |
| 577 | |
| 578 void CPDFSDK_FormFillEnvironment::ClearAllFocusedAnnots() { | |
| 579 for (auto& it : m_pageMap) { | |
| 580 if (it.second->IsValidSDKAnnot(GetFocusAnnot())) | |
| 581 KillFocusAnnot(0); | |
| 582 } | |
| 583 } | |
| 584 | |
| 585 CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView( | |
| 586 UnderlyingPageType* pUnderlyingPage, | |
| 587 bool ReNew) { | |
|
Tom Sepez
2016/10/12 18:52:59
nit: |renew| or |bRenew| (has bugged me for years
dsinclair
2016/10/12 19:44:29
Done.
| |
| 588 auto it = m_pageMap.find(pUnderlyingPage); | |
| 589 if (it != m_pageMap.end()) | |
| 590 return it->second; | |
| 591 | |
| 592 if (!ReNew) | |
| 593 return nullptr; | |
| 594 | |
| 595 CPDFSDK_PageView* pPageView = new CPDFSDK_PageView(this, pUnderlyingPage); | |
| 596 m_pageMap[pUnderlyingPage] = pPageView; | |
| 597 // Delay to load all the annotations, to avoid endless loop. | |
| 598 pPageView->LoadFXAnnots(); | |
| 599 return pPageView; | |
| 600 } | |
| 601 | |
| 602 CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetCurrentView() { | |
| 603 UnderlyingPageType* pPage = | |
| 604 UnderlyingFromFPDFPage(GetCurrentPage(m_pUnderlyingDoc)); | |
| 605 return pPage ? GetPageView(pPage, true) : nullptr; | |
| 606 } | |
| 607 | |
| 608 CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView(int nIndex) { | |
| 609 UnderlyingPageType* pTempPage = | |
| 610 UnderlyingFromFPDFPage(GetPage(m_pUnderlyingDoc, nIndex)); | |
| 611 if (!pTempPage) | |
| 612 return nullptr; | |
| 613 | |
| 614 auto it = m_pageMap.find(pTempPage); | |
| 615 return it != m_pageMap.end() ? it->second : nullptr; | |
| 616 } | |
| 617 | |
| 618 void CPDFSDK_FormFillEnvironment::ProcJavascriptFun() { | |
| 619 CPDF_Document* pPDFDoc = GetPDFDocument(); | |
| 620 CPDF_DocJSActions docJS(pPDFDoc); | |
| 621 int iCount = docJS.CountJSActions(); | |
| 622 if (iCount < 1) | |
| 623 return; | |
| 624 for (int i = 0; i < iCount; i++) { | |
| 625 CFX_ByteString csJSName; | |
| 626 CPDF_Action jsAction = docJS.GetJSAction(i, csJSName); | |
| 627 if (GetActionHander()) { | |
| 628 GetActionHander()->DoAction_JavaScript( | |
| 629 jsAction, CFX_WideString::FromLocal(csJSName.AsStringC()), this); | |
| 630 } | |
| 631 } | |
| 632 } | |
| 633 | |
| 634 FX_BOOL CPDFSDK_FormFillEnvironment::ProcOpenAction() { | |
| 635 if (!m_pUnderlyingDoc) | |
| 636 return FALSE; | |
| 637 | |
| 638 CPDF_Dictionary* pRoot = GetPDFDocument()->GetRoot(); | |
| 639 if (!pRoot) | |
| 640 return FALSE; | |
| 641 | |
| 642 CPDF_Object* pOpenAction = pRoot->GetDictFor("OpenAction"); | |
| 643 if (!pOpenAction) | |
| 644 pOpenAction = pRoot->GetArrayFor("OpenAction"); | |
| 645 | |
| 646 if (!pOpenAction) | |
| 647 return FALSE; | |
| 648 | |
| 649 if (pOpenAction->IsArray()) | |
| 650 return TRUE; | |
| 651 | |
| 652 if (CPDF_Dictionary* pDict = pOpenAction->AsDictionary()) { | |
| 653 CPDF_Action action(pDict); | |
| 654 if (GetActionHander()) | |
| 655 GetActionHander()->DoAction_DocOpen(action, this); | |
| 656 return TRUE; | |
| 657 } | |
| 658 return FALSE; | |
| 659 } | |
| 660 | |
| 661 void CPDFSDK_FormFillEnvironment::RemovePageView( | |
| 662 UnderlyingPageType* pUnderlyingPage) { | |
| 663 auto it = m_pageMap.find(pUnderlyingPage); | |
| 664 if (it == m_pageMap.end()) | |
| 665 return; | |
| 666 | |
| 667 CPDFSDK_PageView* pPageView = it->second; | |
| 668 if (pPageView->IsLocked() || pPageView->IsBeingDestroyed()) | |
| 669 return; | |
| 670 | |
| 671 // Mark the page view so we do not come into |RemovePageView| a second | |
| 672 // time while we're in the process of removing. | |
| 673 pPageView->SetBeingDestroyed(); | |
| 674 | |
| 675 // This must happen before we remove |pPageView| from the map because | |
| 676 // |KillFocusAnnot| can call into the |GetPage| method which will | |
| 677 // look for this page view in the map, if it doesn't find it a new one will | |
| 678 // be created. We then have two page views pointing to the same page and | |
| 679 // bad things happen. | |
| 680 if (pPageView->IsValidSDKAnnot(GetFocusAnnot())) | |
| 681 KillFocusAnnot(0); | |
| 682 | |
| 683 // Remove the page from the map to make sure we don't accidentally attempt | |
| 684 // to use the |pPageView| while we're cleaning it up. | |
| 685 m_pageMap.erase(it); | |
| 686 | |
| 687 delete pPageView; | |
| 688 } | |
| 689 | |
| 690 UnderlyingPageType* CPDFSDK_FormFillEnvironment::GetPage(int nIndex) { | |
| 691 return UnderlyingFromFPDFPage(GetPage(m_pUnderlyingDoc, nIndex)); | |
| 692 } | |
| 693 | |
| 694 CPDFSDK_InterForm* CPDFSDK_FormFillEnvironment::GetInterForm() { | |
| 695 if (!m_pInterForm) | |
| 696 m_pInterForm = pdfium::MakeUnique<CPDFSDK_InterForm>(this); | |
| 697 return m_pInterForm.get(); | |
| 698 } | |
| 699 | |
| 700 void CPDFSDK_FormFillEnvironment::UpdateAllViews(CPDFSDK_PageView* pSender, | |
| 701 CPDFSDK_Annot* pAnnot) { | |
| 702 for (const auto& it : m_pageMap) { | |
| 703 CPDFSDK_PageView* pPageView = it.second; | |
| 704 if (pPageView != pSender) | |
| 705 pPageView->UpdateView(pAnnot); | |
| 706 } | |
| 707 } | |
| 708 | |
| 709 FX_BOOL CPDFSDK_FormFillEnvironment::SetFocusAnnot( | |
| 710 CPDFSDK_Annot::ObservedPtr* pAnnot) { | |
| 711 if (m_bBeingDestroyed) | |
| 712 return FALSE; | |
| 713 if (m_pFocusAnnot == *pAnnot) | |
| 714 return TRUE; | |
| 715 if (m_pFocusAnnot && !KillFocusAnnot(0)) | |
| 716 return FALSE; | |
| 717 if (!*pAnnot) | |
| 718 return FALSE; | |
| 719 | |
| 720 #ifdef PDF_ENABLE_XFA | |
| 721 CPDFSDK_Annot::ObservedPtr pLastFocusAnnot(m_pFocusAnnot.Get()); | |
| 722 #endif // PDF_ENABLE_XFA | |
| 723 CPDFSDK_PageView* pPageView = (*pAnnot)->GetPageView(); | |
| 724 if (pPageView && pPageView->IsValid()) { | |
| 725 CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr(); | |
| 726 if (!m_pFocusAnnot) { | |
| 727 #ifdef PDF_ENABLE_XFA | |
| 728 if (!pAnnotHandler->Annot_OnChangeFocus(pAnnot, &pLastFocusAnnot)) | |
| 729 return FALSE; | |
| 730 #endif // PDF_ENABLE_XFA | |
| 731 if (!pAnnotHandler->Annot_OnSetFocus(pAnnot, 0)) | |
| 732 return FALSE; | |
| 733 if (!m_pFocusAnnot) { | |
| 734 m_pFocusAnnot.Reset(pAnnot->Get()); | |
| 735 return TRUE; | |
| 736 } | |
| 737 } | |
| 738 } | |
| 739 return FALSE; | |
| 740 } | |
| 741 | |
| 742 FX_BOOL CPDFSDK_FormFillEnvironment::KillFocusAnnot(uint32_t nFlag) { | |
| 743 if (m_pFocusAnnot) { | |
| 744 CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr(); | |
| 745 CPDFSDK_Annot::ObservedPtr pFocusAnnot(m_pFocusAnnot.Get()); | |
| 746 m_pFocusAnnot.Reset(); | |
| 747 | |
| 748 #ifdef PDF_ENABLE_XFA | |
| 749 CPDFSDK_Annot::ObservedPtr pNull; | |
| 750 if (!pAnnotHandler->Annot_OnChangeFocus(&pNull, &pFocusAnnot)) | |
| 751 return FALSE; | |
| 752 #endif // PDF_ENABLE_XFA | |
| 753 | |
| 754 if (pAnnotHandler->Annot_OnKillFocus(&pFocusAnnot, nFlag)) { | |
| 755 if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) { | |
| 756 CPDFSDK_Widget* pWidget = | |
| 757 static_cast<CPDFSDK_Widget*>(pFocusAnnot.Get()); | |
| 758 int nFieldType = pWidget->GetFieldType(); | |
| 759 if (FIELDTYPE_TEXTFIELD == nFieldType || | |
| 760 FIELDTYPE_COMBOBOX == nFieldType) { | |
| 761 OnSetFieldInputFocus(nullptr, 0, FALSE); | |
| 762 } | |
| 763 } | |
| 764 if (!m_pFocusAnnot) | |
| 765 return TRUE; | |
| 766 } else { | |
| 767 m_pFocusAnnot.Reset(pFocusAnnot.Get()); | |
| 768 } | |
| 769 } | |
| 770 return FALSE; | |
| 771 } | |
| 772 | |
| 773 FX_BOOL CPDFSDK_FormFillEnvironment::GetPermissions(int nFlag) { | |
| 774 return GetPDFDocument()->GetUserPermissions() & nFlag; | |
| 775 } | |
| OLD | NEW |