blob: 339aeab8c6383ec1c4ae11c7da94b8eff55c1607 [file] [log] [blame]
dsinclairf34518b2016-09-13 12:03:48 -07001// 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/include/cpdfsdk_document.h"
8
9#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
10#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
11#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
12#include "core/fpdfapi/fpdf_parser/include/cpdf_object.h"
13#include "core/fpdfdoc/include/cpdf_action.h"
14#include "core/fpdfdoc/include/cpdf_docjsactions.h"
15#include "core/fpdfdoc/include/cpdf_occontext.h"
dsinclairf34518b2016-09-13 12:03:48 -070016#include "fpdfsdk/include/cpdfsdk_annot.h"
17#include "fpdfsdk/include/cpdfsdk_annothandlermgr.h"
dsinclair79db6092016-09-14 07:27:21 -070018#include "fpdfsdk/include/cpdfsdk_environment.h"
dsinclairf34518b2016-09-13 12:03:48 -070019#include "fpdfsdk/include/cpdfsdk_interform.h"
20#include "fpdfsdk/include/cpdfsdk_pageview.h"
21#include "fpdfsdk/include/cpdfsdk_widget.h"
22#include "fpdfsdk/include/fsdk_actionhandler.h"
23
24// static
25CPDFSDK_Document* CPDFSDK_Document::FromFPDFFormHandle(
26 FPDF_FORMHANDLE hHandle) {
dsinclair79db6092016-09-14 07:27:21 -070027 CPDFSDK_Environment* pEnv = static_cast<CPDFSDK_Environment*>(hHandle);
dsinclairf34518b2016-09-13 12:03:48 -070028 return pEnv ? pEnv->GetSDKDocument() : nullptr;
29}
30
31CPDFSDK_Document::CPDFSDK_Document(UnderlyingDocumentType* pDoc,
dsinclair79db6092016-09-14 07:27:21 -070032 CPDFSDK_Environment* pEnv)
dsinclairf34518b2016-09-13 12:03:48 -070033 : m_pDoc(pDoc),
34 m_pFocusAnnot(nullptr),
35 m_pEnv(pEnv),
36 m_bChangeMask(FALSE),
37 m_bBeingDestroyed(FALSE) {}
38
39CPDFSDK_Document::~CPDFSDK_Document() {
40 m_bBeingDestroyed = TRUE;
41
42 for (auto& it : m_pageMap)
43 it.second->KillFocusAnnotIfNeeded();
44
45 for (auto& it : m_pageMap)
46 delete it.second;
47 m_pageMap.clear();
48}
49
50CPDFSDK_PageView* CPDFSDK_Document::GetPageView(
51 UnderlyingPageType* pUnderlyingPage,
52 bool ReNew) {
53 auto it = m_pageMap.find(pUnderlyingPage);
54 if (it != m_pageMap.end())
55 return it->second;
56
57 if (!ReNew)
58 return nullptr;
59
60 CPDFSDK_PageView* pPageView = new CPDFSDK_PageView(this, pUnderlyingPage);
61 m_pageMap[pUnderlyingPage] = pPageView;
62 // Delay to load all the annotations, to avoid endless loop.
63 pPageView->LoadFXAnnots();
64 return pPageView;
65}
66
67CPDFSDK_PageView* CPDFSDK_Document::GetCurrentView() {
68 UnderlyingPageType* pPage =
dsinclair1f248902016-09-14 10:38:17 -070069 UnderlyingFromFPDFPage(m_pEnv->GetCurrentPage(m_pDoc));
dsinclairf34518b2016-09-13 12:03:48 -070070 return pPage ? GetPageView(pPage, true) : nullptr;
71}
72
73CPDFSDK_PageView* CPDFSDK_Document::GetPageView(int nIndex) {
74 UnderlyingPageType* pTempPage =
dsinclair1f248902016-09-14 10:38:17 -070075 UnderlyingFromFPDFPage(m_pEnv->GetPage(m_pDoc, nIndex));
dsinclairf34518b2016-09-13 12:03:48 -070076 if (!pTempPage)
77 return nullptr;
78
79 auto it = m_pageMap.find(pTempPage);
80 return it != m_pageMap.end() ? it->second : nullptr;
81}
82
83void CPDFSDK_Document::ProcJavascriptFun() {
84 CPDF_Document* pPDFDoc = GetPDFDocument();
85 CPDF_DocJSActions docJS(pPDFDoc);
86 int iCount = docJS.CountJSActions();
87 if (iCount < 1)
88 return;
89 for (int i = 0; i < iCount; i++) {
90 CFX_ByteString csJSName;
91 CPDF_Action jsAction = docJS.GetJSAction(i, csJSName);
92 if (m_pEnv->GetActionHander())
93 m_pEnv->GetActionHander()->DoAction_JavaScript(
94 jsAction, CFX_WideString::FromLocal(csJSName.AsStringC()), this);
95 }
96}
97
98FX_BOOL CPDFSDK_Document::ProcOpenAction() {
99 if (!m_pDoc)
100 return FALSE;
101
102 CPDF_Dictionary* pRoot = GetPDFDocument()->GetRoot();
103 if (!pRoot)
104 return FALSE;
105
dsinclair38fd8442016-09-15 10:15:32 -0700106 CPDF_Object* pOpenAction = pRoot->GetDictFor("OpenAction");
dsinclairf34518b2016-09-13 12:03:48 -0700107 if (!pOpenAction)
dsinclair38fd8442016-09-15 10:15:32 -0700108 pOpenAction = pRoot->GetArrayFor("OpenAction");
dsinclairf34518b2016-09-13 12:03:48 -0700109
110 if (!pOpenAction)
111 return FALSE;
112
113 if (pOpenAction->IsArray())
114 return TRUE;
115
116 if (CPDF_Dictionary* pDict = pOpenAction->AsDictionary()) {
117 CPDF_Action action(pDict);
118 if (m_pEnv->GetActionHander())
119 m_pEnv->GetActionHander()->DoAction_DocOpen(action, this);
120 return TRUE;
121 }
122 return FALSE;
123}
124
125CPDF_OCContext* CPDFSDK_Document::GetOCContext() {
126 if (!m_pOccontent) {
127 m_pOccontent.reset(
128 new CPDF_OCContext(GetPDFDocument(), CPDF_OCContext::View));
129 }
130 return m_pOccontent.get();
131}
132
133void CPDFSDK_Document::RemovePageView(UnderlyingPageType* pUnderlyingPage) {
134 auto it = m_pageMap.find(pUnderlyingPage);
135 if (it == m_pageMap.end())
136 return;
137
138 CPDFSDK_PageView* pPageView = it->second;
139 if (pPageView->IsLocked())
140 return;
141
142 // This must happen before we remove |pPageView| from the map because
143 // |KillFocusAnnotIfNeeded| can call into the |GetPage| method which will
144 // look for this page view in the map, if it doesn't find it a new one will
145 // be created. We then have two page views pointing to the same page and
146 // bad things happen.
147 pPageView->KillFocusAnnotIfNeeded();
148
149 // Remove the page from the map to make sure we don't accidentally attempt
150 // to use the |pPageView| while we're cleaning it up.
151 m_pageMap.erase(it);
152
153 delete pPageView;
154}
155
156UnderlyingPageType* CPDFSDK_Document::GetPage(int nIndex) {
dsinclair1f248902016-09-14 10:38:17 -0700157 return UnderlyingFromFPDFPage(m_pEnv->GetPage(m_pDoc, nIndex));
dsinclairf34518b2016-09-13 12:03:48 -0700158}
159
160CPDFSDK_InterForm* CPDFSDK_Document::GetInterForm() {
161 if (!m_pInterForm)
162 m_pInterForm.reset(new CPDFSDK_InterForm(this));
163 return m_pInterForm.get();
164}
165
166void CPDFSDK_Document::UpdateAllViews(CPDFSDK_PageView* pSender,
167 CPDFSDK_Annot* pAnnot) {
168 for (const auto& it : m_pageMap) {
169 CPDFSDK_PageView* pPageView = it.second;
170 if (pPageView != pSender) {
171 pPageView->UpdateView(pAnnot);
172 }
173 }
174}
175
176CPDFSDK_Annot* CPDFSDK_Document::GetFocusAnnot() {
177 return m_pFocusAnnot;
178}
179
180FX_BOOL CPDFSDK_Document::SetFocusAnnot(CPDFSDK_Annot* pAnnot, FX_UINT nFlag) {
181 if (m_bBeingDestroyed)
182 return FALSE;
183
184 if (m_pFocusAnnot == pAnnot)
185 return TRUE;
186
187 if (m_pFocusAnnot) {
188 if (!KillFocusAnnot(nFlag))
189 return FALSE;
190 }
191
192 if (!pAnnot)
193 return FALSE;
194
195#ifdef PDF_ENABLE_XFA
196 CPDFSDK_Annot* pLastFocusAnnot = m_pFocusAnnot;
197#endif // PDF_ENABLE_XFA
198 CPDFSDK_PageView* pPageView = pAnnot->GetPageView();
199 if (pPageView && pPageView->IsValid()) {
200 CPDFSDK_AnnotHandlerMgr* pAnnotHandler = m_pEnv->GetAnnotHandlerMgr();
201 if (!m_pFocusAnnot) {
202#ifdef PDF_ENABLE_XFA
203 if (!pAnnotHandler->Annot_OnChangeFocus(pAnnot, pLastFocusAnnot))
204 return FALSE;
205#endif // PDF_ENABLE_XFA
206 if (!pAnnotHandler->Annot_OnSetFocus(pAnnot, nFlag))
207 return FALSE;
208 if (!m_pFocusAnnot) {
209 m_pFocusAnnot = pAnnot;
210 return TRUE;
211 }
212 }
213 }
214 return FALSE;
215}
216
217FX_BOOL CPDFSDK_Document::KillFocusAnnot(FX_UINT nFlag) {
218 if (m_pFocusAnnot) {
219 CPDFSDK_AnnotHandlerMgr* pAnnotHandler = m_pEnv->GetAnnotHandlerMgr();
220 CPDFSDK_Annot* pFocusAnnot = m_pFocusAnnot;
221 m_pFocusAnnot = nullptr;
222
223#ifdef PDF_ENABLE_XFA
224 if (!pAnnotHandler->Annot_OnChangeFocus(nullptr, pFocusAnnot))
225 return FALSE;
226#endif // PDF_ENABLE_XFA
227
228 if (pAnnotHandler->Annot_OnKillFocus(pFocusAnnot, nFlag)) {
229 if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) {
230 CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pFocusAnnot;
231 int nFieldType = pWidget->GetFieldType();
232 if (FIELDTYPE_TEXTFIELD == nFieldType ||
233 FIELDTYPE_COMBOBOX == nFieldType) {
dsinclair1f248902016-09-14 10:38:17 -0700234 m_pEnv->OnSetFieldInputFocus(nullptr, nullptr, 0, FALSE);
dsinclairf34518b2016-09-13 12:03:48 -0700235 }
236 }
237
238 if (!m_pFocusAnnot)
239 return TRUE;
240 } else {
241 m_pFocusAnnot = pFocusAnnot;
242 }
243 }
244 return FALSE;
245}
246
247void CPDFSDK_Document::OnCloseDocument() {
248 KillFocusAnnot();
249}
250
251FX_BOOL CPDFSDK_Document::GetPermissions(int nFlag) {
252 return GetPDFDocument()->GetUserPermissions() & nFlag;
253}
254
255IJS_Runtime* CPDFSDK_Document::GetJsRuntime() {
256 return m_pEnv->GetJSRuntime();
257}
258
259CFX_WideString CPDFSDK_Document::GetPath() {
260 return m_pEnv->JS_docGetFilePath();
261}