Chromium Code Reviews| Index: fpdfsdk/cpdfsdk_formfillenvironment.cpp |
| diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp |
| index 7b41ea148c04413c53fdeb0825adcbd19501f407..2beaadeb1a9e5d59349eb7503f693159a02b5526 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) |
|
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.
|
| + 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) { |
|
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.
|
| + 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; |
| +} |