| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| 6 | |
| 7 #include "fpdfsdk/cpdfsdk_document.h" | |
| 8 | |
| 9 #include "core/fpdfapi/parser/cpdf_array.h" | |
| 10 #include "core/fpdfapi/parser/cpdf_dictionary.h" | |
| 11 #include "core/fpdfapi/parser/cpdf_document.h" | |
| 12 #include "core/fpdfapi/parser/cpdf_object.h" | |
| 13 #include "core/fpdfdoc/cpdf_action.h" | |
| 14 #include "core/fpdfdoc/cpdf_docjsactions.h" | |
| 15 #include "core/fpdfdoc/cpdf_occontext.h" | |
| 16 #include "fpdfsdk/cpdfsdk_annot.h" | |
| 17 #include "fpdfsdk/cpdfsdk_annothandlermgr.h" | |
| 18 #include "fpdfsdk/cpdfsdk_formfillenvironment.h" | |
| 19 #include "fpdfsdk/cpdfsdk_interform.h" | |
| 20 #include "fpdfsdk/cpdfsdk_pageview.h" | |
| 21 #include "fpdfsdk/cpdfsdk_widget.h" | |
| 22 #include "fpdfsdk/fsdk_actionhandler.h" | |
| 23 #include "third_party/base/ptr_util.h" | |
| 24 | |
| 25 CPDFSDK_Document::CPDFSDK_Document(UnderlyingDocumentType* pDoc, | |
| 26 CPDFSDK_FormFillEnvironment* pEnv) | |
| 27 : m_pDoc(pDoc), | |
| 28 m_pEnv(pEnv), | |
| 29 m_bChangeMask(FALSE), | |
| 30 m_bBeingDestroyed(FALSE) {} | |
| 31 | |
| 32 CPDFSDK_Document::~CPDFSDK_Document() { | |
| 33 m_bBeingDestroyed = TRUE; | |
| 34 | |
| 35 ClearAllFocusedAnnots(); | |
| 36 for (auto& it : m_pageMap) | |
| 37 delete it.second; | |
| 38 m_pageMap.clear(); | |
| 39 } | |
| 40 | |
| 41 void CPDFSDK_Document::ClearAllFocusedAnnots() { | |
| 42 for (auto& it : m_pageMap) { | |
| 43 if (it.second->IsValidSDKAnnot(GetFocusAnnot())) | |
| 44 KillFocusAnnot(0); | |
| 45 } | |
| 46 } | |
| 47 | |
| 48 CPDFSDK_PageView* CPDFSDK_Document::GetPageView( | |
| 49 UnderlyingPageType* pUnderlyingPage, | |
| 50 bool ReNew) { | |
| 51 auto it = m_pageMap.find(pUnderlyingPage); | |
| 52 if (it != m_pageMap.end()) | |
| 53 return it->second; | |
| 54 | |
| 55 if (!ReNew) | |
| 56 return nullptr; | |
| 57 | |
| 58 CPDFSDK_PageView* pPageView = new CPDFSDK_PageView(GetEnv(), pUnderlyingPage); | |
| 59 m_pageMap[pUnderlyingPage] = pPageView; | |
| 60 // Delay to load all the annotations, to avoid endless loop. | |
| 61 pPageView->LoadFXAnnots(); | |
| 62 return pPageView; | |
| 63 } | |
| 64 | |
| 65 CPDFSDK_PageView* CPDFSDK_Document::GetCurrentView() { | |
| 66 UnderlyingPageType* pPage = | |
| 67 UnderlyingFromFPDFPage(m_pEnv->GetCurrentPage(m_pDoc)); | |
| 68 return pPage ? GetPageView(pPage, true) : nullptr; | |
| 69 } | |
| 70 | |
| 71 CPDFSDK_PageView* CPDFSDK_Document::GetPageView(int nIndex) { | |
| 72 UnderlyingPageType* pTempPage = | |
| 73 UnderlyingFromFPDFPage(m_pEnv->GetPage(m_pDoc, nIndex)); | |
| 74 if (!pTempPage) | |
| 75 return nullptr; | |
| 76 | |
| 77 auto it = m_pageMap.find(pTempPage); | |
| 78 return it != m_pageMap.end() ? it->second : nullptr; | |
| 79 } | |
| 80 | |
| 81 void CPDFSDK_Document::ProcJavascriptFun() { | |
| 82 CPDF_Document* pPDFDoc = GetPDFDocument(); | |
| 83 CPDF_DocJSActions docJS(pPDFDoc); | |
| 84 int iCount = docJS.CountJSActions(); | |
| 85 if (iCount < 1) | |
| 86 return; | |
| 87 for (int i = 0; i < iCount; i++) { | |
| 88 CFX_ByteString csJSName; | |
| 89 CPDF_Action jsAction = docJS.GetJSAction(i, csJSName); | |
| 90 if (m_pEnv->GetActionHander()) | |
| 91 m_pEnv->GetActionHander()->DoAction_JavaScript( | |
| 92 jsAction, CFX_WideString::FromLocal(csJSName.AsStringC()), GetEnv()); | |
| 93 } | |
| 94 } | |
| 95 | |
| 96 FX_BOOL CPDFSDK_Document::ProcOpenAction() { | |
| 97 if (!m_pDoc) | |
| 98 return FALSE; | |
| 99 | |
| 100 CPDF_Dictionary* pRoot = GetPDFDocument()->GetRoot(); | |
| 101 if (!pRoot) | |
| 102 return FALSE; | |
| 103 | |
| 104 CPDF_Object* pOpenAction = pRoot->GetDictFor("OpenAction"); | |
| 105 if (!pOpenAction) | |
| 106 pOpenAction = pRoot->GetArrayFor("OpenAction"); | |
| 107 | |
| 108 if (!pOpenAction) | |
| 109 return FALSE; | |
| 110 | |
| 111 if (pOpenAction->IsArray()) | |
| 112 return TRUE; | |
| 113 | |
| 114 if (CPDF_Dictionary* pDict = pOpenAction->AsDictionary()) { | |
| 115 CPDF_Action action(pDict); | |
| 116 if (m_pEnv->GetActionHander()) | |
| 117 m_pEnv->GetActionHander()->DoAction_DocOpen(action, GetEnv()); | |
| 118 return TRUE; | |
| 119 } | |
| 120 return FALSE; | |
| 121 } | |
| 122 | |
| 123 void CPDFSDK_Document::RemovePageView(UnderlyingPageType* pUnderlyingPage) { | |
| 124 auto it = m_pageMap.find(pUnderlyingPage); | |
| 125 if (it == m_pageMap.end()) | |
| 126 return; | |
| 127 | |
| 128 CPDFSDK_PageView* pPageView = it->second; | |
| 129 if (pPageView->IsLocked() || pPageView->IsBeingDestroyed()) | |
| 130 return; | |
| 131 | |
| 132 // Mark the page view so we do not come into |RemovePageView| a second | |
| 133 // time while we're in the process of removing. | |
| 134 pPageView->SetBeingDestroyed(); | |
| 135 | |
| 136 // This must happen before we remove |pPageView| from the map because | |
| 137 // |KillFocusAnnot| can call into the |GetPage| method which will | |
| 138 // look for this page view in the map, if it doesn't find it a new one will | |
| 139 // be created. We then have two page views pointing to the same page and | |
| 140 // bad things happen. | |
| 141 if (pPageView->IsValidSDKAnnot(GetFocusAnnot())) | |
| 142 KillFocusAnnot(0); | |
| 143 | |
| 144 // Remove the page from the map to make sure we don't accidentally attempt | |
| 145 // to use the |pPageView| while we're cleaning it up. | |
| 146 m_pageMap.erase(it); | |
| 147 | |
| 148 delete pPageView; | |
| 149 } | |
| 150 | |
| 151 UnderlyingPageType* CPDFSDK_Document::GetPage(int nIndex) { | |
| 152 return UnderlyingFromFPDFPage(m_pEnv->GetPage(m_pDoc, nIndex)); | |
| 153 } | |
| 154 | |
| 155 CPDFSDK_InterForm* CPDFSDK_Document::GetInterForm() { | |
| 156 if (!m_pInterForm) | |
| 157 m_pInterForm = pdfium::MakeUnique<CPDFSDK_InterForm>(GetEnv()); | |
| 158 return m_pInterForm.get(); | |
| 159 } | |
| 160 | |
| 161 void CPDFSDK_Document::UpdateAllViews(CPDFSDK_PageView* pSender, | |
| 162 CPDFSDK_Annot* pAnnot) { | |
| 163 for (const auto& it : m_pageMap) { | |
| 164 CPDFSDK_PageView* pPageView = it.second; | |
| 165 if (pPageView != pSender) | |
| 166 pPageView->UpdateView(pAnnot); | |
| 167 } | |
| 168 } | |
| 169 | |
| 170 FX_BOOL CPDFSDK_Document::SetFocusAnnot(CPDFSDK_Annot::ObservedPtr* pAnnot) { | |
| 171 if (m_bBeingDestroyed) | |
| 172 return FALSE; | |
| 173 if (m_pFocusAnnot == *pAnnot) | |
| 174 return TRUE; | |
| 175 if (m_pFocusAnnot && !KillFocusAnnot(0)) | |
| 176 return FALSE; | |
| 177 if (!*pAnnot) | |
| 178 return FALSE; | |
| 179 | |
| 180 #ifdef PDF_ENABLE_XFA | |
| 181 CPDFSDK_Annot::ObservedPtr pLastFocusAnnot(m_pFocusAnnot.Get()); | |
| 182 #endif // PDF_ENABLE_XFA | |
| 183 CPDFSDK_PageView* pPageView = (*pAnnot)->GetPageView(); | |
| 184 if (pPageView && pPageView->IsValid()) { | |
| 185 CPDFSDK_AnnotHandlerMgr* pAnnotHandler = m_pEnv->GetAnnotHandlerMgr(); | |
| 186 if (!m_pFocusAnnot) { | |
| 187 #ifdef PDF_ENABLE_XFA | |
| 188 if (!pAnnotHandler->Annot_OnChangeFocus(pAnnot, &pLastFocusAnnot)) | |
| 189 return FALSE; | |
| 190 #endif // PDF_ENABLE_XFA | |
| 191 if (!pAnnotHandler->Annot_OnSetFocus(pAnnot, 0)) | |
| 192 return FALSE; | |
| 193 if (!m_pFocusAnnot) { | |
| 194 m_pFocusAnnot.Reset(pAnnot->Get()); | |
| 195 return TRUE; | |
| 196 } | |
| 197 } | |
| 198 } | |
| 199 return FALSE; | |
| 200 } | |
| 201 | |
| 202 FX_BOOL CPDFSDK_Document::KillFocusAnnot(uint32_t nFlag) { | |
| 203 if (m_pFocusAnnot) { | |
| 204 CPDFSDK_AnnotHandlerMgr* pAnnotHandler = m_pEnv->GetAnnotHandlerMgr(); | |
| 205 CPDFSDK_Annot::ObservedPtr pFocusAnnot(m_pFocusAnnot.Get()); | |
| 206 m_pFocusAnnot.Reset(); | |
| 207 | |
| 208 #ifdef PDF_ENABLE_XFA | |
| 209 CPDFSDK_Annot::ObservedPtr pNull; | |
| 210 if (!pAnnotHandler->Annot_OnChangeFocus(&pNull, &pFocusAnnot)) | |
| 211 return FALSE; | |
| 212 #endif // PDF_ENABLE_XFA | |
| 213 | |
| 214 if (pAnnotHandler->Annot_OnKillFocus(&pFocusAnnot, nFlag)) { | |
| 215 if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) { | |
| 216 CPDFSDK_Widget* pWidget = | |
| 217 static_cast<CPDFSDK_Widget*>(pFocusAnnot.Get()); | |
| 218 int nFieldType = pWidget->GetFieldType(); | |
| 219 if (FIELDTYPE_TEXTFIELD == nFieldType || | |
| 220 FIELDTYPE_COMBOBOX == nFieldType) { | |
| 221 m_pEnv->OnSetFieldInputFocus(nullptr, 0, FALSE); | |
| 222 } | |
| 223 } | |
| 224 if (!m_pFocusAnnot) | |
| 225 return TRUE; | |
| 226 } else { | |
| 227 m_pFocusAnnot.Reset(pFocusAnnot.Get()); | |
| 228 } | |
| 229 } | |
| 230 return FALSE; | |
| 231 } | |
| 232 | |
| 233 void CPDFSDK_Document::OnCloseDocument() { | |
| 234 KillFocusAnnot(0); | |
| 235 } | |
| 236 | |
| 237 FX_BOOL CPDFSDK_Document::GetPermissions(int nFlag) { | |
| 238 return GetPDFDocument()->GetUserPermissions() & nFlag; | |
| 239 } | |
| 240 | |
| 241 IJS_Runtime* CPDFSDK_Document::GetJsRuntime() { | |
| 242 return m_pEnv->GetJSRuntime(); | |
| 243 } | |
| 244 | |
| 245 CFX_WideString CPDFSDK_Document::GetPath() { | |
| 246 return m_pEnv->JS_docGetFilePath(); | |
| 247 } | |
| OLD | NEW |