1 // Copyright 2014 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 "xfa/fxfa/cxfa_ffdoc.h"
8
9 #include <algorithm>
10 #include <memory>
11
12 #include "core/fpdfapi/parser/cpdf_dictionary.h"
13 #include "core/fpdfapi/parser/cpdf_document.h"
14 #include "core/fpdfapi/parser/cpdf_stream.h"
15 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
16 #include "core/fpdfdoc/cpdf_nametree.h"
17 #include "core/fxcrt/cfx_readonlymemorystream.h"
18 #include "core/fxcrt/fx_extension.h"
19 #include "core/fxcrt/xml/cfx_xmldocument.h"
20 #include "core/fxcrt/xml/cfx_xmlelement.h"
21 #include "core/fxcrt/xml/cfx_xmlnode.h"
22 #include "core/fxcrt/xml/cfx_xmlparser.h"
23 #include "core/fxge/dib/cfx_dibitmap.h"
24 #include "fxjs/xfa/cjx_object.h"
25 #include "third_party/base/check.h"
26 #include "third_party/base/ptr_util.h"
27 #include "v8/include/cppgc/allocation.h"
28 #include "v8/include/cppgc/heap.h"
29 #include "xfa/fgas/font/cfgas_pdffontmgr.h"
30 #include "xfa/fwl/cfwl_notedriver.h"
31 #include "xfa/fxfa/cxfa_ffapp.h"
32 #include "xfa/fxfa/cxfa_ffdocview.h"
33 #include "xfa/fxfa/cxfa_ffnotify.h"
34 #include "xfa/fxfa/cxfa_ffwidget.h"
35 #include "xfa/fxfa/cxfa_fontmgr.h"
36 #include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
37 #include "xfa/fxfa/parser/cxfa_acrobat.h"
38 #include "xfa/fxfa/parser/cxfa_acrobat7.h"
39 #include "xfa/fxfa/parser/cxfa_dataexporter.h"
40 #include "xfa/fxfa/parser/cxfa_document.h"
41 #include "xfa/fxfa/parser/cxfa_document_builder.h"
42 #include "xfa/fxfa/parser/cxfa_dynamicrender.h"
43 #include "xfa/fxfa/parser/cxfa_node.h"
44
45 FX_IMAGEDIB_AND_DPI::FX_IMAGEDIB_AND_DPI() = default;
46 FX_IMAGEDIB_AND_DPI::FX_IMAGEDIB_AND_DPI(const FX_IMAGEDIB_AND_DPI& that) =
47 default;
48
FX_IMAGEDIB_AND_DPI(const RetainPtr<CFX_DIBBase> & pDib,int32_t xDpi,int32_t yDpi)49 FX_IMAGEDIB_AND_DPI::FX_IMAGEDIB_AND_DPI(const RetainPtr<CFX_DIBBase>& pDib,
50 int32_t xDpi,
51 int32_t yDpi)
52 : pDibSource(pDib), iImageXDpi(xDpi), iImageYDpi(yDpi) {}
53
54 FX_IMAGEDIB_AND_DPI::~FX_IMAGEDIB_AND_DPI() = default;
55
CXFA_FFDoc(CXFA_FFApp * pApp,IXFA_DocEnvironment * pDocEnvironment,CPDF_Document * pPDFDoc,cppgc::Heap * pHeap)56 CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp,
57 IXFA_DocEnvironment* pDocEnvironment,
58 CPDF_Document* pPDFDoc,
59 cppgc::Heap* pHeap)
60 : m_pDocEnvironment(pDocEnvironment),
61 m_pPDFDoc(pPDFDoc),
62 m_pHeap(pHeap),
63 m_pApp(pApp),
64 m_pNotify(cppgc::MakeGarbageCollected<CXFA_FFNotify>(
65 pHeap->GetAllocationHandle(),
66 this)),
67 m_pDocument(cppgc::MakeGarbageCollected<CXFA_Document>(
68 pHeap->GetAllocationHandle(),
69 m_pNotify,
70 pHeap,
71 cppgc::MakeGarbageCollected<CXFA_LayoutProcessor>(
72 pHeap->GetAllocationHandle(),
73 pHeap))) {}
74
75 CXFA_FFDoc::~CXFA_FFDoc() = default;
76
PreFinalize()77 void CXFA_FFDoc::PreFinalize() {
78 if (m_DocView)
79 m_DocView->RunDocClose();
80
81 if (m_pDocument)
82 m_pDocument->ClearLayoutData();
83 }
84
Trace(cppgc::Visitor * visitor) const85 void CXFA_FFDoc::Trace(cppgc::Visitor* visitor) const {
86 visitor->Trace(m_pApp);
87 visitor->Trace(m_pNotify);
88 visitor->Trace(m_pDocument);
89 visitor->Trace(m_DocView);
90 }
91
BuildDoc(CFX_XMLDocument * pXML)92 bool CXFA_FFDoc::BuildDoc(CFX_XMLDocument* pXML) {
93 if (!pXML)
94 return false;
95
96 CXFA_DocumentBuilder builder(m_pDocument);
97 if (!builder.BuildDocument(pXML, XFA_PacketType::Xdp))
98 return false;
99
100 m_pDocument->SetRoot(builder.GetRootNode());
101 return true;
102 }
103
CreateDocView()104 CXFA_FFDocView* CXFA_FFDoc::CreateDocView() {
105 if (!m_DocView) {
106 m_DocView = cppgc::MakeGarbageCollected<CXFA_FFDocView>(
107 m_pHeap->GetAllocationHandle(), this);
108 }
109 return m_DocView;
110 }
111
SetChangeMark()112 void CXFA_FFDoc::SetChangeMark() {
113 m_pDocEnvironment->SetChangeMark(this);
114 }
115
InvalidateRect(CXFA_FFPageView * pPageView,const CFX_RectF & rt)116 void CXFA_FFDoc::InvalidateRect(CXFA_FFPageView* pPageView,
117 const CFX_RectF& rt) {
118 m_pDocEnvironment->InvalidateRect(pPageView, rt);
119 }
120
DisplayCaret(CXFA_FFWidget * hWidget,bool bVisible,const CFX_RectF * pRtAnchor)121 void CXFA_FFDoc::DisplayCaret(CXFA_FFWidget* hWidget,
122 bool bVisible,
123 const CFX_RectF* pRtAnchor) {
124 return m_pDocEnvironment->DisplayCaret(hWidget, bVisible, pRtAnchor);
125 }
126
GetPopupPos(CXFA_FFWidget * hWidget,float fMinPopup,float fMaxPopup,const CFX_RectF & rtAnchor,CFX_RectF * pPopupRect) const127 bool CXFA_FFDoc::GetPopupPos(CXFA_FFWidget* hWidget,
128 float fMinPopup,
129 float fMaxPopup,
130 const CFX_RectF& rtAnchor,
131 CFX_RectF* pPopupRect) const {
132 return m_pDocEnvironment->GetPopupPos(hWidget, fMinPopup, fMaxPopup, rtAnchor,
133 pPopupRect);
134 }
135
PopupMenu(CXFA_FFWidget * hWidget,const CFX_PointF & ptPopup)136 bool CXFA_FFDoc::PopupMenu(CXFA_FFWidget* hWidget, const CFX_PointF& ptPopup) {
137 return m_pDocEnvironment->PopupMenu(hWidget, ptPopup);
138 }
139
PageViewEvent(CXFA_FFPageView * pPageView,uint32_t dwFlags)140 void CXFA_FFDoc::PageViewEvent(CXFA_FFPageView* pPageView, uint32_t dwFlags) {
141 m_pDocEnvironment->PageViewEvent(pPageView, dwFlags);
142 }
143
WidgetPostAdd(CXFA_FFWidget * hWidget)144 void CXFA_FFDoc::WidgetPostAdd(CXFA_FFWidget* hWidget) {
145 m_pDocEnvironment->WidgetPostAdd(hWidget);
146 }
147
WidgetPreRemove(CXFA_FFWidget * hWidget)148 void CXFA_FFDoc::WidgetPreRemove(CXFA_FFWidget* hWidget) {
149 m_pDocEnvironment->WidgetPreRemove(hWidget);
150 }
151
CountPages() const152 int32_t CXFA_FFDoc::CountPages() const {
153 return m_pDocEnvironment->CountPages(this);
154 }
155
GetCurrentPage() const156 int32_t CXFA_FFDoc::GetCurrentPage() const {
157 return m_pDocEnvironment->GetCurrentPage(this);
158 }
159
SetCurrentPage(int32_t iCurPage)160 void CXFA_FFDoc::SetCurrentPage(int32_t iCurPage) {
161 m_pDocEnvironment->SetCurrentPage(this, iCurPage);
162 }
163
IsCalculationsEnabled() const164 bool CXFA_FFDoc::IsCalculationsEnabled() const {
165 return m_pDocEnvironment->IsCalculationsEnabled(this);
166 }
167
SetCalculationsEnabled(bool bEnabled)168 void CXFA_FFDoc::SetCalculationsEnabled(bool bEnabled) {
169 return m_pDocEnvironment->SetCalculationsEnabled(this, bEnabled);
170 }
171
GetTitle() const172 WideString CXFA_FFDoc::GetTitle() const {
173 return m_pDocEnvironment->GetTitle(this);
174 }
175
SetTitle(const WideString & wsTitle)176 void CXFA_FFDoc::SetTitle(const WideString& wsTitle) {
177 m_pDocEnvironment->SetTitle(this, wsTitle);
178 }
179
ExportData(const WideString & wsFilePath,bool bXDP)180 void CXFA_FFDoc::ExportData(const WideString& wsFilePath, bool bXDP) {
181 m_pDocEnvironment->ExportData(this, wsFilePath, bXDP);
182 }
183
GotoURL(const WideString & bsURL)184 void CXFA_FFDoc::GotoURL(const WideString& bsURL) {
185 m_pDocEnvironment->GotoURL(this, bsURL);
186 }
187
IsValidationsEnabled() const188 bool CXFA_FFDoc::IsValidationsEnabled() const {
189 return m_pDocEnvironment->IsValidationsEnabled(this);
190 }
191
SetValidationsEnabled(bool bEnabled)192 void CXFA_FFDoc::SetValidationsEnabled(bool bEnabled) {
193 m_pDocEnvironment->SetValidationsEnabled(this, bEnabled);
194 }
195
SetFocusWidget(CXFA_FFWidget * hWidget)196 void CXFA_FFDoc::SetFocusWidget(CXFA_FFWidget* hWidget) {
197 m_pDocEnvironment->SetFocusWidget(this, hWidget);
198 }
199
Print(int32_t nStartPage,int32_t nEndPage,uint32_t dwOptions)200 void CXFA_FFDoc::Print(int32_t nStartPage,
201 int32_t nEndPage,
202 uint32_t dwOptions) {
203 m_pDocEnvironment->Print(this, nStartPage, nEndPage, dwOptions);
204 }
205
GetHighlightColor() const206 FX_ARGB CXFA_FFDoc::GetHighlightColor() const {
207 return m_pDocEnvironment->GetHighlightColor(this);
208 }
209
GetIJSRuntime() const210 IJS_Runtime* CXFA_FFDoc::GetIJSRuntime() const {
211 return m_pDocEnvironment->GetIJSRuntime(this);
212 }
213
GetXMLDocument() const214 CFX_XMLDocument* CXFA_FFDoc::GetXMLDocument() const {
215 return m_pDocEnvironment->GetXMLDoc();
216 }
217
OpenLinkedFile(const WideString & wsLink)218 RetainPtr<IFX_SeekableReadStream> CXFA_FFDoc::OpenLinkedFile(
219 const WideString& wsLink) {
220 return m_pDocEnvironment->OpenLinkedFile(this, wsLink);
221 }
222
GetDocView(CXFA_LayoutProcessor * pLayout)223 CXFA_FFDocView* CXFA_FFDoc::GetDocView(CXFA_LayoutProcessor* pLayout) {
224 return m_DocView && m_DocView->GetLayoutProcessor() == pLayout ? m_DocView
225 : nullptr;
226 }
227
GetDocView()228 CXFA_FFDocView* CXFA_FFDoc::GetDocView() {
229 return m_DocView;
230 }
231
OpenDoc(CFX_XMLDocument * pXML)232 bool CXFA_FFDoc::OpenDoc(CFX_XMLDocument* pXML) {
233 if (!BuildDoc(pXML))
234 return false;
235
236 // At this point we've got an XFA document and we want to always return
237 // true to signify the load succeeded.
238 m_pPDFFontMgr = std::make_unique<CFGAS_PDFFontMgr>(GetPDFDoc());
239 m_FormType = FormType::kXFAForeground;
240 CXFA_Node* pConfig = ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config));
241 if (!pConfig)
242 return true;
243
244 CXFA_Acrobat* pAcrobat =
245 pConfig->GetFirstChildByClass<CXFA_Acrobat>(XFA_Element::Acrobat);
246 if (!pAcrobat)
247 return true;
248
249 CXFA_Acrobat7* pAcrobat7 =
250 pAcrobat->GetFirstChildByClass<CXFA_Acrobat7>(XFA_Element::Acrobat7);
251 if (!pAcrobat7)
252 return true;
253
254 CXFA_DynamicRender* pDynamicRender =
255 pAcrobat7->GetFirstChildByClass<CXFA_DynamicRender>(
256 XFA_Element::DynamicRender);
257 if (!pDynamicRender)
258 return true;
259
260 WideString wsType = pDynamicRender->JSObject()->GetContent(false);
261 if (wsType.EqualsASCII("required"))
262 m_FormType = FormType::kXFAFull;
263
264 return true;
265 }
266
GetPDFNamedImage(WideStringView wsName,int32_t & iImageXDpi,int32_t & iImageYDpi)267 RetainPtr<CFX_DIBitmap> CXFA_FFDoc::GetPDFNamedImage(WideStringView wsName,
268 int32_t& iImageXDpi,
269 int32_t& iImageYDpi) {
270 uint32_t dwHash = FX_HashCode_GetW(wsName, false);
271 auto it = m_HashToDibDpiMap.find(dwHash);
272 if (it != m_HashToDibDpiMap.end()) {
273 iImageXDpi = it->second.iImageXDpi;
274 iImageYDpi = it->second.iImageYDpi;
275 return it->second.pDibSource.As<CFX_DIBitmap>();
276 }
277
278 auto name_tree = CPDF_NameTree::Create(m_pPDFDoc.Get(), "XFAImages");
279 size_t count = name_tree ? name_tree->GetCount() : 0;
280 if (count == 0)
281 return nullptr;
282
283 CPDF_Object* pObject = name_tree->LookupValue(WideString(wsName));
284 if (!pObject) {
285 for (size_t i = 0; i < count; ++i) {
286 WideString wsTemp;
287 CPDF_Object* pTempObject = name_tree->LookupValueAndName(i, &wsTemp);
288 if (wsTemp == wsName) {
289 pObject = pTempObject;
290 break;
291 }
292 }
293 }
294
295 CPDF_Stream* pStream = ToStream(pObject);
296 if (!pStream)
297 return nullptr;
298
299 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
300 pAcc->LoadAllDataFiltered();
301
302 auto pImageFileRead =
303 pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(pAcc->GetSpan());
304
305 RetainPtr<CFX_DIBitmap> pDibSource = XFA_LoadImageFromBuffer(
306 pImageFileRead, FXCODEC_IMAGE_UNKNOWN, iImageXDpi, iImageYDpi);
307 m_HashToDibDpiMap[dwHash] = {pDibSource, iImageXDpi, iImageYDpi};
308 return pDibSource;
309 }
310
SavePackage(CXFA_Node * pNode,const RetainPtr<IFX_SeekableStream> & pFile)311 bool CXFA_FFDoc::SavePackage(CXFA_Node* pNode,
312 const RetainPtr<IFX_SeekableStream>& pFile) {
313 DCHECK(pNode || GetXFADoc()->GetRoot());
314
315 CXFA_DataExporter exporter;
316 return exporter.Export(pFile, pNode ? pNode : GetXFADoc()->GetRoot());
317 }
318