diff options
Diffstat (limited to 'fpdfsdk/cpdfsdk_formfillenvironment.cpp')
-rw-r--r-- | fpdfsdk/cpdfsdk_formfillenvironment.cpp | 217 |
1 files changed, 214 insertions, 3 deletions
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp index 7b41ea148c..2beaadeb1a 100644 --- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp +++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp @@ -8,8 +8,12 @@ #include <memory> +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfdoc/cpdf_docjsactions.h" #include "fpdfsdk/cpdfsdk_annothandlermgr.h" -#include "fpdfsdk/cpdfsdk_document.h" +#include "fpdfsdk/cpdfsdk_interform.h" +#include "fpdfsdk/cpdfsdk_pageview.h" +#include "fpdfsdk/cpdfsdk_widget.h" #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" #include "fpdfsdk/fsdk_actionhandler.h" #include "fpdfsdk/javascript/ijs_runtime.h" @@ -34,11 +38,19 @@ CPDFSDK_FormFillEnvironment::CPDFSDK_FormFillEnvironment( UnderlyingDocumentType* pDoc, FPDF_FORMFILLINFO* pFFinfo) : m_pInfo(pFFinfo), - m_pSDKDoc(new CPDFSDK_Document(pDoc, this)), m_pUnderlyingDoc(pDoc), - m_pSysHandler(new CFX_SystemHandler(this)) {} + m_pSysHandler(new CFX_SystemHandler(this)), + m_bChangeMask(FALSE), + m_bBeingDestroyed(FALSE) {} CPDFSDK_FormFillEnvironment::~CPDFSDK_FormFillEnvironment() { + m_bBeingDestroyed = TRUE; + + ClearAllFocusedAnnots(); + for (auto& it : m_pageMap) + delete it.second; + m_pageMap.clear(); + // |m_pAnnotHandlerMgr| will try to access |m_pFormFiller| // when it cleans up. So, we must make sure it is cleaned up before // |m_pFormFiller|. @@ -562,3 +574,202 @@ void CPDFSDK_FormFillEnvironment::PageEvent(int iPageCount, m_pInfo->FFI_PageEvent(m_pInfo, iPageCount, dwEventType); } #endif // PDF_ENABLE_XFA + +void CPDFSDK_FormFillEnvironment::ClearAllFocusedAnnots() { + for (auto& it : m_pageMap) { + if (it.second->IsValidSDKAnnot(GetFocusAnnot())) + KillFocusAnnot(0); + } +} + +CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView( + UnderlyingPageType* pUnderlyingPage, + bool ReNew) { + auto it = m_pageMap.find(pUnderlyingPage); + if (it != m_pageMap.end()) + return it->second; + + if (!ReNew) + return nullptr; + + CPDFSDK_PageView* pPageView = new CPDFSDK_PageView(this, pUnderlyingPage); + m_pageMap[pUnderlyingPage] = pPageView; + // Delay to load all the annotations, to avoid endless loop. + pPageView->LoadFXAnnots(); + return pPageView; +} + +CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetCurrentView() { + UnderlyingPageType* pPage = + UnderlyingFromFPDFPage(GetCurrentPage(m_pUnderlyingDoc)); + return pPage ? GetPageView(pPage, true) : nullptr; +} + +CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView(int nIndex) { + UnderlyingPageType* pTempPage = + UnderlyingFromFPDFPage(GetPage(m_pUnderlyingDoc, nIndex)); + if (!pTempPage) + return nullptr; + + auto it = m_pageMap.find(pTempPage); + return it != m_pageMap.end() ? it->second : nullptr; +} + +void CPDFSDK_FormFillEnvironment::ProcJavascriptFun() { + CPDF_Document* pPDFDoc = GetPDFDocument(); + CPDF_DocJSActions docJS(pPDFDoc); + int iCount = docJS.CountJSActions(); + if (iCount < 1) + return; + for (int i = 0; i < iCount; i++) { + CFX_ByteString csJSName; + CPDF_Action jsAction = docJS.GetJSAction(i, csJSName); + if (GetActionHander()) { + GetActionHander()->DoAction_JavaScript( + jsAction, CFX_WideString::FromLocal(csJSName.AsStringC()), this); + } + } +} + +FX_BOOL CPDFSDK_FormFillEnvironment::ProcOpenAction() { + if (!m_pUnderlyingDoc) + return FALSE; + + CPDF_Dictionary* pRoot = GetPDFDocument()->GetRoot(); + if (!pRoot) + return FALSE; + + CPDF_Object* pOpenAction = pRoot->GetDictFor("OpenAction"); + if (!pOpenAction) + pOpenAction = pRoot->GetArrayFor("OpenAction"); + + if (!pOpenAction) + return FALSE; + + if (pOpenAction->IsArray()) + return TRUE; + + if (CPDF_Dictionary* pDict = pOpenAction->AsDictionary()) { + CPDF_Action action(pDict); + if (GetActionHander()) + GetActionHander()->DoAction_DocOpen(action, this); + return TRUE; + } + return FALSE; +} + +void CPDFSDK_FormFillEnvironment::RemovePageView( + UnderlyingPageType* pUnderlyingPage) { + auto it = m_pageMap.find(pUnderlyingPage); + if (it == m_pageMap.end()) + return; + + CPDFSDK_PageView* pPageView = it->second; + if (pPageView->IsLocked() || pPageView->IsBeingDestroyed()) + return; + + // Mark the page view so we do not come into |RemovePageView| a second + // time while we're in the process of removing. + pPageView->SetBeingDestroyed(); + + // This must happen before we remove |pPageView| from the map because + // |KillFocusAnnot| can call into the |GetPage| method which will + // look for this page view in the map, if it doesn't find it a new one will + // be created. We then have two page views pointing to the same page and + // bad things happen. + if (pPageView->IsValidSDKAnnot(GetFocusAnnot())) + KillFocusAnnot(0); + + // Remove the page from the map to make sure we don't accidentally attempt + // to use the |pPageView| while we're cleaning it up. + m_pageMap.erase(it); + + delete pPageView; +} + +UnderlyingPageType* CPDFSDK_FormFillEnvironment::GetPage(int nIndex) { + return UnderlyingFromFPDFPage(GetPage(m_pUnderlyingDoc, nIndex)); +} + +CPDFSDK_InterForm* CPDFSDK_FormFillEnvironment::GetInterForm() { + if (!m_pInterForm) + m_pInterForm = pdfium::MakeUnique<CPDFSDK_InterForm>(this); + return m_pInterForm.get(); +} + +void CPDFSDK_FormFillEnvironment::UpdateAllViews(CPDFSDK_PageView* pSender, + CPDFSDK_Annot* pAnnot) { + for (const auto& it : m_pageMap) { + CPDFSDK_PageView* pPageView = it.second; + if (pPageView != pSender) + pPageView->UpdateView(pAnnot); + } +} + +FX_BOOL CPDFSDK_FormFillEnvironment::SetFocusAnnot( + CPDFSDK_Annot::ObservedPtr* pAnnot) { + if (m_bBeingDestroyed) + return FALSE; + if (m_pFocusAnnot == *pAnnot) + return TRUE; + if (m_pFocusAnnot && !KillFocusAnnot(0)) + return FALSE; + if (!*pAnnot) + return FALSE; + +#ifdef PDF_ENABLE_XFA + CPDFSDK_Annot::ObservedPtr pLastFocusAnnot(m_pFocusAnnot.Get()); +#endif // PDF_ENABLE_XFA + CPDFSDK_PageView* pPageView = (*pAnnot)->GetPageView(); + if (pPageView && pPageView->IsValid()) { + CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr(); + if (!m_pFocusAnnot) { +#ifdef PDF_ENABLE_XFA + if (!pAnnotHandler->Annot_OnChangeFocus(pAnnot, &pLastFocusAnnot)) + return FALSE; +#endif // PDF_ENABLE_XFA + if (!pAnnotHandler->Annot_OnSetFocus(pAnnot, 0)) + return FALSE; + if (!m_pFocusAnnot) { + m_pFocusAnnot.Reset(pAnnot->Get()); + return TRUE; + } + } + } + return FALSE; +} + +FX_BOOL CPDFSDK_FormFillEnvironment::KillFocusAnnot(uint32_t nFlag) { + if (m_pFocusAnnot) { + CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr(); + CPDFSDK_Annot::ObservedPtr pFocusAnnot(m_pFocusAnnot.Get()); + m_pFocusAnnot.Reset(); + +#ifdef PDF_ENABLE_XFA + CPDFSDK_Annot::ObservedPtr pNull; + if (!pAnnotHandler->Annot_OnChangeFocus(&pNull, &pFocusAnnot)) + return FALSE; +#endif // PDF_ENABLE_XFA + + if (pAnnotHandler->Annot_OnKillFocus(&pFocusAnnot, nFlag)) { + if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) { + CPDFSDK_Widget* pWidget = + static_cast<CPDFSDK_Widget*>(pFocusAnnot.Get()); + int nFieldType = pWidget->GetFieldType(); + if (FIELDTYPE_TEXTFIELD == nFieldType || + FIELDTYPE_COMBOBOX == nFieldType) { + OnSetFieldInputFocus(nullptr, 0, FALSE); + } + } + if (!m_pFocusAnnot) + return TRUE; + } else { + m_pFocusAnnot.Reset(pFocusAnnot.Get()); + } + } + return FALSE; +} + +FX_BOOL CPDFSDK_FormFillEnvironment::GetPermissions(int nFlag) { + return GetPDFDocument()->GetUserPermissions() & nFlag; +} |