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 |