• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ffdocview.h"
8 
9 #include "core/fxcrt/fx_extension.h"
10 #include "fxjs/cfxjse_engine.h"
11 #include "fxjs/xfa/cjx_object.h"
12 #include "third_party/base/ptr_util.h"
13 #include "third_party/base/stl_util.h"
14 #include "xfa/fxfa/cxfa_ffapp.h"
15 #include "xfa/fxfa/cxfa_ffbarcode.h"
16 #include "xfa/fxfa/cxfa_ffcheckbutton.h"
17 #include "xfa/fxfa/cxfa_ffdoc.h"
18 #include "xfa/fxfa/cxfa_ffdraw.h"
19 #include "xfa/fxfa/cxfa_ffexclgroup.h"
20 #include "xfa/fxfa/cxfa_fffield.h"
21 #include "xfa/fxfa/cxfa_ffimage.h"
22 #include "xfa/fxfa/cxfa_ffimageedit.h"
23 #include "xfa/fxfa/cxfa_ffpageview.h"
24 #include "xfa/fxfa/cxfa_ffpushbutton.h"
25 #include "xfa/fxfa/cxfa_ffsignature.h"
26 #include "xfa/fxfa/cxfa_ffsubform.h"
27 #include "xfa/fxfa/cxfa_fftext.h"
28 #include "xfa/fxfa/cxfa_ffwidget.h"
29 #include "xfa/fxfa/cxfa_ffwidgethandler.h"
30 #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
31 #include "xfa/fxfa/cxfa_textprovider.h"
32 #include "xfa/fxfa/cxfa_widgetacciterator.h"
33 #include "xfa/fxfa/parser/cxfa_acrobat.h"
34 #include "xfa/fxfa/parser/cxfa_binditems.h"
35 #include "xfa/fxfa/parser/cxfa_calculate.h"
36 #include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
37 #include "xfa/fxfa/parser/cxfa_pageset.h"
38 #include "xfa/fxfa/parser/cxfa_present.h"
39 #include "xfa/fxfa/parser/cxfa_subform.h"
40 #include "xfa/fxfa/parser/cxfa_validate.h"
41 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
42 
43 const XFA_AttributeEnum gs_EventActivity[] = {
44     XFA_AttributeEnum::Click,      XFA_AttributeEnum::Change,
45     XFA_AttributeEnum::DocClose,   XFA_AttributeEnum::DocReady,
46     XFA_AttributeEnum::Enter,      XFA_AttributeEnum::Exit,
47     XFA_AttributeEnum::Full,       XFA_AttributeEnum::IndexChange,
48     XFA_AttributeEnum::Initialize, XFA_AttributeEnum::MouseDown,
49     XFA_AttributeEnum::MouseEnter, XFA_AttributeEnum::MouseExit,
50     XFA_AttributeEnum::MouseUp,    XFA_AttributeEnum::PostExecute,
51     XFA_AttributeEnum::PostOpen,   XFA_AttributeEnum::PostPrint,
52     XFA_AttributeEnum::PostSave,   XFA_AttributeEnum::PostSign,
53     XFA_AttributeEnum::PostSubmit, XFA_AttributeEnum::PreExecute,
54     XFA_AttributeEnum::PreOpen,    XFA_AttributeEnum::PrePrint,
55     XFA_AttributeEnum::PreSave,    XFA_AttributeEnum::PreSign,
56     XFA_AttributeEnum::PreSubmit,  XFA_AttributeEnum::Ready,
57     XFA_AttributeEnum::Unknown,
58 };
59 
CXFA_FFDocView(CXFA_FFDoc * pDoc)60 CXFA_FFDocView::CXFA_FFDocView(CXFA_FFDoc* pDoc)
61     : m_bLayoutEvent(false),
62       m_pListFocusWidget(nullptr),
63       m_bInLayoutStatus(false),
64       m_pDoc(pDoc),
65       m_pXFADocLayout(nullptr),
66       m_iStatus(XFA_DOCVIEW_LAYOUTSTATUS_None),
67       m_iLock(0) {}
68 
~CXFA_FFDocView()69 CXFA_FFDocView::~CXFA_FFDocView() {
70   DestroyDocView();
71 }
72 
InitLayout(CXFA_Node * pNode)73 void CXFA_FFDocView::InitLayout(CXFA_Node* pNode) {
74   RunBindItems();
75   ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Initialize, false, true,
76                                nullptr);
77   ExecEventActivityByDeepFirst(pNode, XFA_EVENT_IndexChange, false, true,
78                                nullptr);
79 }
80 
StartLayout(int32_t iStartPage)81 int32_t CXFA_FFDocView::StartLayout(int32_t iStartPage) {
82   m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start;
83   m_pDoc->GetXFADoc()->DoProtoMerge();
84   m_pDoc->GetXFADoc()->DoDataMerge();
85   m_pXFADocLayout = GetXFALayout();
86 
87   int32_t iStatus = m_pXFADocLayout->StartLayout();
88   if (iStatus < 0)
89     return iStatus;
90 
91   CXFA_Node* pRootItem =
92       ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
93   if (!pRootItem)
94     return iStatus;
95 
96   InitLayout(pRootItem);
97   InitCalculate(pRootItem);
98   InitValidate(pRootItem);
99 
100   ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, true, true, nullptr);
101   m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start;
102   return iStatus;
103 }
104 
DoLayout()105 int32_t CXFA_FFDocView::DoLayout() {
106   int32_t iStatus = 100;
107   iStatus = m_pXFADocLayout->DoLayout();
108   if (iStatus != 100)
109     return iStatus;
110 
111   m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Doing;
112   return iStatus;
113 }
114 
StopLayout()115 void CXFA_FFDocView::StopLayout() {
116   CXFA_Node* pRootItem =
117       ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
118   if (!pRootItem)
119     return;
120 
121   CXFA_Subform* pSubformNode =
122       pRootItem->GetChild<CXFA_Subform>(0, XFA_Element::Subform, false);
123   if (!pSubformNode)
124     return;
125 
126   CXFA_PageSet* pPageSetNode =
127       pSubformNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet);
128   if (!pPageSetNode)
129     return;
130 
131   RunCalculateWidgets();
132   RunValidate();
133 
134   InitLayout(pPageSetNode);
135   InitCalculate(pPageSetNode);
136   InitValidate(pPageSetNode);
137 
138   ExecEventActivityByDeepFirst(pPageSetNode, XFA_EVENT_Ready, true, true,
139                                nullptr);
140   ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true,
141                                nullptr);
142   ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocReady, false, true,
143                                nullptr);
144 
145   RunCalculateWidgets();
146   RunValidate();
147 
148   if (RunLayout()) {
149     ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true,
150                                  nullptr);
151   }
152 
153   m_CalculateAccs.clear();
154   if (m_pFocusAcc && !m_pFocusWidget)
155     SetFocusWidgetAcc(m_pFocusAcc.Get());
156 
157   m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_End;
158 }
159 
ShowNullTestMsg()160 void CXFA_FFDocView::ShowNullTestMsg() {
161   int32_t iCount = pdfium::CollectionSize<int32_t>(m_arrNullTestMsg);
162   CXFA_FFApp* pApp = m_pDoc->GetApp();
163   IXFA_AppProvider* pAppProvider = pApp->GetAppProvider();
164   if (pAppProvider && iCount) {
165     int32_t iRemain = iCount > 7 ? iCount - 7 : 0;
166     iCount -= iRemain;
167     WideString wsMsg;
168     for (int32_t i = 0; i < iCount; i++)
169       wsMsg += m_arrNullTestMsg[i] + L"\n";
170 
171     if (iRemain > 0) {
172       wsMsg += L"\n" + WideString::Format(
173                            L"Message limit exceeded. Remaining %d "
174                            L"validation errors not reported.",
175                            iRemain);
176     }
177     pAppProvider->MsgBox(wsMsg, pAppProvider->GetAppTitle(), XFA_MBICON_Status,
178                          XFA_MB_OK);
179   }
180   m_arrNullTestMsg.clear();
181 }
182 
UpdateDocView()183 void CXFA_FFDocView::UpdateDocView() {
184   if (IsUpdateLocked())
185     return;
186 
187   LockUpdate();
188   for (CXFA_Node* pNode : m_NewAddedNodes) {
189     InitCalculate(pNode);
190     InitValidate(pNode);
191     ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true, nullptr);
192   }
193   m_NewAddedNodes.clear();
194 
195   RunSubformIndexChange();
196   RunCalculateWidgets();
197   RunValidate();
198 
199   ShowNullTestMsg();
200 
201   if (RunLayout() && m_bLayoutEvent)
202     RunEventLayoutReady();
203 
204   m_bLayoutEvent = false;
205   m_CalculateAccs.clear();
206   RunInvalidate();
207   UnlockUpdate();
208 }
209 
CountPageViews() const210 int32_t CXFA_FFDocView::CountPageViews() const {
211   return m_pXFADocLayout ? m_pXFADocLayout->CountPages() : 0;
212 }
213 
GetPageView(int32_t nIndex) const214 CXFA_FFPageView* CXFA_FFDocView::GetPageView(int32_t nIndex) const {
215   if (!m_pXFADocLayout)
216     return nullptr;
217   return static_cast<CXFA_FFPageView*>(m_pXFADocLayout->GetPage(nIndex));
218 }
219 
GetXFALayout() const220 CXFA_LayoutProcessor* CXFA_FFDocView::GetXFALayout() const {
221   return m_pDoc->GetXFADoc()->GetDocLayout();
222 }
223 
ResetSingleWidgetAccData(CXFA_WidgetAcc * pWidgetAcc)224 bool CXFA_FFDocView::ResetSingleWidgetAccData(CXFA_WidgetAcc* pWidgetAcc) {
225   CXFA_Node* pNode = pWidgetAcc->GetNode();
226   XFA_Element eType = pNode->GetElementType();
227   if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup)
228     return false;
229 
230   pWidgetAcc->ResetData();
231   pWidgetAcc->UpdateUIDisplay(this, nullptr);
232   CXFA_Validate* validate = pNode->GetValidateIfExists();
233   if (!validate)
234     return true;
235 
236   AddValidateWidget(pWidgetAcc);
237   validate->SetFlag(XFA_NodeFlag_NeedsInitApp, false);
238   return true;
239 }
240 
ResetWidgetAcc(CXFA_WidgetAcc * pWidgetAcc)241 void CXFA_FFDocView::ResetWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) {
242   m_bLayoutEvent = true;
243   bool bChanged = false;
244   CXFA_Node* pFormNode = nullptr;
245   if (pWidgetAcc) {
246     bChanged = ResetSingleWidgetAccData(pWidgetAcc);
247     pFormNode = pWidgetAcc->GetNode();
248   } else {
249     pFormNode = GetRootSubform();
250   }
251   if (!pFormNode)
252     return;
253 
254   if (pFormNode->GetElementType() != XFA_Element::Field &&
255       pFormNode->GetElementType() != XFA_Element::ExclGroup) {
256     CXFA_WidgetAccIterator Iterator(pFormNode);
257     while (CXFA_WidgetAcc* pAcc = Iterator.MoveToNext()) {
258       bChanged |= ResetSingleWidgetAccData(pAcc);
259       if (pAcc->GetNode()->GetElementType() == XFA_Element::ExclGroup)
260         Iterator.SkipTree();
261     }
262   }
263   if (bChanged)
264     m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get());
265 }
266 
ProcessWidgetEvent(CXFA_EventParam * pParam,CXFA_WidgetAcc * pWidgetAcc)267 int32_t CXFA_FFDocView::ProcessWidgetEvent(CXFA_EventParam* pParam,
268                                            CXFA_WidgetAcc* pWidgetAcc) {
269   if (!pParam)
270     return XFA_EVENTERROR_Error;
271 
272   if (pParam->m_eType == XFA_EVENT_Validate) {
273     WideString wsValidateStr(L"preSubmit");
274     CXFA_Node* pConfigItem =
275         ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Config));
276     if (pConfigItem) {
277       CXFA_Acrobat* pAcrobatNode =
278           pConfigItem->GetChild<CXFA_Acrobat>(0, XFA_Element::Acrobat, false);
279       CXFA_Validate* pValidateNode =
280           pAcrobatNode ? pAcrobatNode->GetChild<CXFA_Validate>(
281                              0, XFA_Element::Validate, false)
282                        : nullptr;
283       if (!pValidateNode) {
284         CXFA_Present* pPresentNode =
285             pConfigItem->GetChild<CXFA_Present>(0, XFA_Element::Present, false);
286         pValidateNode = pPresentNode ? pPresentNode->GetChild<CXFA_Validate>(
287                                            0, XFA_Element::Validate, false)
288                                      : nullptr;
289       }
290       if (pValidateNode)
291         wsValidateStr = pValidateNode->JSObject()->GetContent(false);
292     }
293 
294     if (!wsValidateStr.Contains(L"preSubmit"))
295       return XFA_EVENTERROR_Success;
296   }
297 
298   CXFA_Node* pNode = pWidgetAcc ? pWidgetAcc->GetNode() : nullptr;
299   if (!pNode) {
300     CXFA_Node* pRootItem =
301         ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
302     if (!pRootItem)
303       return XFA_EVENTERROR_Error;
304 
305     pNode = pRootItem->GetChild<CXFA_Node>(0, XFA_Element::Subform, false);
306   }
307 
308   ExecEventActivityByDeepFirst(pNode, pParam->m_eType, pParam->m_bIsFormReady,
309                                true, nullptr);
310   return XFA_EVENTERROR_Success;
311 }
312 
GetWidgetForNode(CXFA_Node * node)313 CXFA_FFWidget* CXFA_FFDocView::GetWidgetForNode(CXFA_Node* node) {
314   return static_cast<CXFA_FFWidget*>(GetXFALayout()->GetLayoutItem(node));
315 }
316 
GetWidgetHandler()317 CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() {
318   if (!m_pWidgetHandler)
319     m_pWidgetHandler = pdfium::MakeUnique<CXFA_FFWidgetHandler>(this);
320   return m_pWidgetHandler.get();
321 }
322 
323 std::unique_ptr<CXFA_WidgetAccIterator>
CreateWidgetAccIterator()324 CXFA_FFDocView::CreateWidgetAccIterator() {
325   CXFA_Subform* pFormRoot = GetRootSubform();
326   return pFormRoot ? pdfium::MakeUnique<CXFA_WidgetAccIterator>(pFormRoot)
327                    : nullptr;
328 }
329 
KillFocus()330 void CXFA_FFDocView::KillFocus() {
331   if (m_pFocusWidget &&
332       (m_pFocusWidget->GetStatus() & XFA_WidgetStatus_Focused)) {
333     m_pFocusWidget->OnKillFocus(nullptr);
334   }
335   m_pFocusAcc = nullptr;
336   m_pFocusWidget = nullptr;
337   m_pOldFocusWidget = nullptr;
338 }
339 
SetFocus(CXFA_FFWidget * hWidget)340 bool CXFA_FFDocView::SetFocus(CXFA_FFWidget* hWidget) {
341   CXFA_FFWidget* pNewFocus = hWidget;
342   if (m_pOldFocusWidget == pNewFocus)
343     return false;
344 
345   CXFA_FFWidget* pOldFocus = m_pOldFocusWidget.Get();
346   m_pOldFocusWidget = pNewFocus;
347   if (pOldFocus) {
348     if (m_pFocusWidget != m_pOldFocusWidget &&
349         (pOldFocus->GetStatus() & XFA_WidgetStatus_Focused)) {
350       m_pFocusWidget = pOldFocus;
351       pOldFocus->OnKillFocus(pNewFocus);
352     } else if ((pOldFocus->GetStatus() & XFA_WidgetStatus_Visible)) {
353       if (!pOldFocus->IsLoaded())
354         pOldFocus->LoadWidget();
355 
356       pOldFocus->OnSetFocus(m_pFocusWidget.Get());
357       m_pFocusWidget = pOldFocus;
358       pOldFocus->OnKillFocus(pNewFocus);
359     }
360   }
361   if (m_pFocusWidget == m_pOldFocusWidget)
362     return false;
363 
364   pNewFocus = m_pOldFocusWidget.Get();
365   if (m_pListFocusWidget && pNewFocus == m_pListFocusWidget) {
366     m_pFocusAcc = nullptr;
367     m_pFocusWidget = nullptr;
368     m_pListFocusWidget = nullptr;
369     m_pOldFocusWidget = nullptr;
370     return false;
371   }
372   if (pNewFocus && (pNewFocus->GetStatus() & XFA_WidgetStatus_Visible)) {
373     if (!pNewFocus->IsLoaded())
374       pNewFocus->LoadWidget();
375     pNewFocus->OnSetFocus(m_pFocusWidget.Get());
376   }
377   m_pFocusAcc = pNewFocus ? pNewFocus->GetNode()->GetWidgetAcc() : nullptr;
378   m_pFocusWidget = pNewFocus;
379   m_pOldFocusWidget = m_pFocusWidget;
380   return true;
381 }
382 
SetFocusWidgetAcc(CXFA_WidgetAcc * pWidgetAcc)383 void CXFA_FFDocView::SetFocusWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) {
384   CXFA_FFWidget* pNewFocus = nullptr;
385   if (pWidgetAcc)
386     pNewFocus = GetWidgetForNode(pWidgetAcc->GetNode());
387   if (!SetFocus(pNewFocus))
388     return;
389 
390   m_pFocusAcc = pWidgetAcc;
391   if (m_iStatus != XFA_DOCVIEW_LAYOUTSTATUS_End)
392     return;
393 
394   m_pDoc->GetDocEnvironment()->SetFocusWidget(m_pDoc.Get(),
395                                               m_pFocusWidget.Get());
396 }
397 
DeleteLayoutItem(CXFA_FFWidget * pWidget)398 void CXFA_FFDocView::DeleteLayoutItem(CXFA_FFWidget* pWidget) {
399   if (m_pFocusAcc && m_pFocusAcc->GetNode() != pWidget->GetNode())
400     return;
401 
402   m_pFocusAcc = nullptr;
403   m_pFocusWidget = nullptr;
404   m_pOldFocusWidget = nullptr;
405 }
406 
XFA_ProcessEvent(CXFA_FFDocView * pDocView,CXFA_WidgetAcc * pWidgetAcc,CXFA_EventParam * pParam)407 static int32_t XFA_ProcessEvent(CXFA_FFDocView* pDocView,
408                                 CXFA_WidgetAcc* pWidgetAcc,
409                                 CXFA_EventParam* pParam) {
410   if (!pParam || pParam->m_eType == XFA_EVENT_Unknown)
411     return XFA_EVENTERROR_NotExist;
412   if (!pWidgetAcc)
413     return XFA_EVENTERROR_NotExist;
414 
415   CXFA_Node* node = pWidgetAcc->GetNode();
416   if (node && node->GetElementType() == XFA_Element::Draw)
417     return XFA_EVENTERROR_NotExist;
418 
419   switch (pParam->m_eType) {
420     case XFA_EVENT_Calculate:
421       return node->ProcessCalculate(pDocView);
422     case XFA_EVENT_Validate:
423       if (pDocView->GetDoc()->GetDocEnvironment()->IsValidationsEnabled(
424               pDocView->GetDoc())) {
425         return node->ProcessValidate(pDocView, 0x01);
426       }
427       return XFA_EVENTERROR_Disabled;
428     case XFA_EVENT_InitCalculate: {
429       CXFA_Calculate* calc = node->GetCalculateIfExists();
430       if (!calc)
431         return XFA_EVENTERROR_NotExist;
432       if (node->IsUserInteractive())
433         return XFA_EVENTERROR_Disabled;
434 
435       return node->ExecuteScript(pDocView, calc->GetScriptIfExists(), pParam);
436     }
437     default:
438       break;
439   }
440 
441   return node->ProcessEvent(pDocView, gs_EventActivity[pParam->m_eType],
442                             pParam);
443 }
444 
ExecEventActivityByDeepFirst(CXFA_Node * pFormNode,XFA_EVENTTYPE eEventType,bool bIsFormReady,bool bRecursive,CXFA_Node * pExclude)445 int32_t CXFA_FFDocView::ExecEventActivityByDeepFirst(CXFA_Node* pFormNode,
446                                                      XFA_EVENTTYPE eEventType,
447                                                      bool bIsFormReady,
448                                                      bool bRecursive,
449                                                      CXFA_Node* pExclude) {
450   if (pFormNode == pExclude)
451     return XFA_EVENTERROR_NotExist;
452 
453   XFA_Element elementType = pFormNode->GetElementType();
454   if (elementType == XFA_Element::Field) {
455     if (eEventType == XFA_EVENT_IndexChange)
456       return XFA_EVENTERROR_NotExist;
457 
458     CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc();
459     if (!pWidgetAcc)
460       return XFA_EVENTERROR_NotExist;
461 
462     CXFA_EventParam eParam;
463     eParam.m_eType = eEventType;
464     eParam.m_pTarget = pWidgetAcc;
465     eParam.m_bIsFormReady = bIsFormReady;
466     return XFA_ProcessEvent(this, pWidgetAcc, &eParam);
467   }
468 
469   int32_t iRet = XFA_EVENTERROR_NotExist;
470   if (bRecursive) {
471     for (CXFA_Node* pNode = pFormNode->GetFirstContainerChild(); pNode;
472          pNode = pNode->GetNextContainerSibling()) {
473       elementType = pNode->GetElementType();
474       if (elementType != XFA_Element::Variables &&
475           elementType != XFA_Element::Draw) {
476         iRet |= ExecEventActivityByDeepFirst(pNode, eEventType, bIsFormReady,
477                                              bRecursive, pExclude);
478       }
479     }
480   }
481   CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc();
482   if (!pWidgetAcc)
483     return iRet;
484 
485   CXFA_EventParam eParam;
486   eParam.m_eType = eEventType;
487   eParam.m_pTarget = pWidgetAcc;
488   eParam.m_bIsFormReady = bIsFormReady;
489   iRet |= XFA_ProcessEvent(this, pWidgetAcc, &eParam);
490 
491   return iRet;
492 }
493 
GetWidgetByName(const WideString & wsName,CXFA_FFWidget * pRefWidget)494 CXFA_FFWidget* CXFA_FFDocView::GetWidgetByName(const WideString& wsName,
495                                                CXFA_FFWidget* pRefWidget) {
496   CXFA_WidgetAcc* pRefAcc =
497       pRefWidget ? pRefWidget->GetNode()->GetWidgetAcc() : nullptr;
498   CXFA_WidgetAcc* pAcc = GetWidgetAccByName(wsName, pRefAcc);
499   if (!pAcc)
500     return nullptr;
501   return GetWidgetForNode(pAcc->GetNode());
502 }
503 
GetWidgetAccByName(const WideString & wsName,CXFA_WidgetAcc * pRefWidgetAcc)504 CXFA_WidgetAcc* CXFA_FFDocView::GetWidgetAccByName(
505     const WideString& wsName,
506     CXFA_WidgetAcc* pRefWidgetAcc) {
507   WideString wsExpression;
508   uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
509                      XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
510   CFXJSE_Engine* pScriptContext = m_pDoc->GetXFADoc()->GetScriptContext();
511   if (!pScriptContext)
512     return nullptr;
513 
514   CXFA_Node* refNode = nullptr;
515   if (pRefWidgetAcc) {
516     refNode = pRefWidgetAcc->GetNode();
517     wsExpression = wsName;
518   } else {
519     wsExpression = L"$form." + wsName;
520   }
521 
522   XFA_RESOLVENODE_RS resolveNodeRS;
523   if (!pScriptContext->ResolveObjects(refNode, wsExpression.AsStringView(),
524                                       &resolveNodeRS, dwStyle, nullptr)) {
525     return nullptr;
526   }
527 
528   if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) {
529     CXFA_Node* pNode = resolveNodeRS.objects.front()->AsNode();
530     if (pNode)
531       return pNode->GetWidgetAcc();
532   }
533   return nullptr;
534 }
535 
OnPageEvent(CXFA_ContainerLayoutItem * pSender,uint32_t dwEvent)536 void CXFA_FFDocView::OnPageEvent(CXFA_ContainerLayoutItem* pSender,
537                                  uint32_t dwEvent) {
538   CXFA_FFPageView* pFFPageView = static_cast<CXFA_FFPageView*>(pSender);
539   m_pDoc->GetDocEnvironment()->PageViewEvent(pFFPageView, dwEvent);
540 }
541 
542 
AddInvalidateRect(CXFA_FFWidget * pWidget,const CFX_RectF & rtInvalidate)543 void CXFA_FFDocView::AddInvalidateRect(CXFA_FFWidget* pWidget,
544                                        const CFX_RectF& rtInvalidate) {
545   AddInvalidateRect(pWidget->GetPageView(), rtInvalidate);
546 }
547 
AddInvalidateRect(CXFA_FFPageView * pPageView,const CFX_RectF & rtInvalidate)548 void CXFA_FFDocView::AddInvalidateRect(CXFA_FFPageView* pPageView,
549                                        const CFX_RectF& rtInvalidate) {
550   if (m_mapPageInvalidate[pPageView]) {
551     m_mapPageInvalidate[pPageView]->Union(rtInvalidate);
552     return;
553   }
554 
555   m_mapPageInvalidate[pPageView] = pdfium::MakeUnique<CFX_RectF>(rtInvalidate);
556 }
557 
RunInvalidate()558 void CXFA_FFDocView::RunInvalidate() {
559   for (const auto& pair : m_mapPageInvalidate)
560     m_pDoc->GetDocEnvironment()->InvalidateRect(pair.first, *pair.second);
561 
562   m_mapPageInvalidate.clear();
563 }
564 
RunLayout()565 bool CXFA_FFDocView::RunLayout() {
566   LockUpdate();
567   m_bInLayoutStatus = true;
568   if (!m_pXFADocLayout->IncrementLayout() &&
569       m_pXFADocLayout->StartLayout() < 100) {
570     m_pXFADocLayout->DoLayout();
571     UnlockUpdate();
572     m_bInLayoutStatus = false;
573     m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr,
574                                                XFA_PAGEVIEWEVENT_StopLayout);
575     return true;
576   }
577 
578   m_bInLayoutStatus = false;
579   m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr,
580                                              XFA_PAGEVIEWEVENT_StopLayout);
581   UnlockUpdate();
582   return false;
583 }
584 
RunSubformIndexChange()585 void CXFA_FFDocView::RunSubformIndexChange() {
586   for (CXFA_Node* pSubformNode : m_IndexChangedSubforms) {
587     if (!pSubformNode->GetWidgetAcc())
588       continue;
589 
590     CXFA_EventParam eParam;
591     eParam.m_eType = XFA_EVENT_IndexChange;
592     eParam.m_pTarget = pSubformNode->GetWidgetAcc();
593     pSubformNode->ProcessEvent(this, XFA_AttributeEnum::IndexChange, &eParam);
594   }
595   m_IndexChangedSubforms.clear();
596 }
597 
AddNewFormNode(CXFA_Node * pNode)598 void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) {
599   m_NewAddedNodes.push_back(pNode);
600   InitLayout(pNode);
601 }
602 
AddIndexChangedSubform(CXFA_Node * pNode)603 void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Node* pNode) {
604   ASSERT(pNode->GetElementType() == XFA_Element::Subform);
605   m_IndexChangedSubforms.push_back(pNode);
606 }
607 
RunDocClose()608 void CXFA_FFDocView::RunDocClose() {
609   CXFA_Node* pRootItem =
610       ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
611   if (!pRootItem)
612     return;
613 
614   ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocClose, false, true,
615                                nullptr);
616 }
617 
DestroyDocView()618 void CXFA_FFDocView::DestroyDocView() {
619   ClearInvalidateList();
620   m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_None;
621   m_iLock = 0;
622   m_ValidateAccs.clear();
623   m_BindItems.clear();
624   m_CalculateAccs.clear();
625 }
626 
AddCalculateWidgetAcc(CXFA_WidgetAcc * pWidgetAcc)627 void CXFA_FFDocView::AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) {
628   CXFA_WidgetAcc* pCurrentAcc =
629       !m_CalculateAccs.empty() ? m_CalculateAccs.back() : nullptr;
630   if (pCurrentAcc != pWidgetAcc)
631     m_CalculateAccs.push_back(pWidgetAcc);
632 }
633 
AddCalculateNodeNotify(CXFA_Node * pNodeChange)634 void CXFA_FFDocView::AddCalculateNodeNotify(CXFA_Node* pNodeChange) {
635   CXFA_CalcData* pGlobalData = pNodeChange->JSObject()->GetCalcData();
636   if (!pGlobalData)
637     return;
638 
639   for (auto* pResult : pGlobalData->m_Globals) {
640     if (!pResult->HasRemovedChildren())
641       AddCalculateWidgetAcc(pResult->GetWidgetAcc());
642   }
643 }
644 
RunCalculateRecursive(size_t index)645 size_t CXFA_FFDocView::RunCalculateRecursive(size_t index) {
646   while (index < m_CalculateAccs.size()) {
647     CXFA_Node* node = m_CalculateAccs[index]->GetNode();
648 
649     AddCalculateNodeNotify(node);
650     size_t recurse = node->JSObject()->GetCalcRecursionCount() + 1;
651     node->JSObject()->SetCalcRecursionCount(recurse);
652     if (recurse > 11)
653       break;
654     if (node->ProcessCalculate(this) == XFA_EVENTERROR_Success)
655       AddValidateWidget(node->GetWidgetAcc());
656 
657     index = RunCalculateRecursive(++index);
658   }
659   return index;
660 }
661 
RunCalculateWidgets()662 int32_t CXFA_FFDocView::RunCalculateWidgets() {
663   if (!m_pDoc->GetDocEnvironment()->IsCalculationsEnabled(m_pDoc.Get()))
664     return XFA_EVENTERROR_Disabled;
665   if (!m_CalculateAccs.empty())
666     RunCalculateRecursive(0);
667 
668   for (CXFA_WidgetAcc* pCurAcc : m_CalculateAccs)
669     pCurAcc->GetNode()->JSObject()->SetCalcRecursionCount(0);
670 
671   m_CalculateAccs.clear();
672   return XFA_EVENTERROR_Success;
673 }
674 
AddValidateWidget(CXFA_WidgetAcc * pWidget)675 void CXFA_FFDocView::AddValidateWidget(CXFA_WidgetAcc* pWidget) {
676   if (!pdfium::ContainsValue(m_ValidateAccs, pWidget))
677     m_ValidateAccs.push_back(pWidget);
678 }
679 
InitCalculate(CXFA_Node * pNode)680 void CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) {
681   ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true,
682                                nullptr);
683 }
684 
ProcessValueChanged(CXFA_WidgetAcc * widgetAcc)685 void CXFA_FFDocView::ProcessValueChanged(CXFA_WidgetAcc* widgetAcc) {
686   AddValidateWidget(widgetAcc);
687   AddCalculateWidgetAcc(widgetAcc);
688   RunCalculateWidgets();
689   RunValidate();
690 }
691 
InitValidate(CXFA_Node * pNode)692 bool CXFA_FFDocView::InitValidate(CXFA_Node* pNode) {
693   if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc.Get()))
694     return false;
695 
696   ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Validate, false, true, nullptr);
697   m_ValidateAccs.clear();
698   return true;
699 }
700 
RunValidate()701 bool CXFA_FFDocView::RunValidate() {
702   if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc.Get()))
703     return false;
704 
705   for (CXFA_WidgetAcc* pAcc : m_ValidateAccs) {
706     CXFA_Node* node = pAcc->GetNode();
707     if (!node->HasRemovedChildren())
708       node->ProcessValidate(this, 0);
709   }
710   m_ValidateAccs.clear();
711   return true;
712 }
713 
RunEventLayoutReady()714 bool CXFA_FFDocView::RunEventLayoutReady() {
715   CXFA_Node* pRootItem =
716       ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
717   if (!pRootItem)
718     return false;
719 
720   ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true,
721                                nullptr);
722   RunLayout();
723   return true;
724 }
725 
RunBindItems()726 void CXFA_FFDocView::RunBindItems() {
727   for (auto* item : m_BindItems) {
728     if (item->HasRemovedChildren())
729       continue;
730 
731     CXFA_Node* pWidgetNode = item->GetParent();
732     CXFA_WidgetAcc* pAcc = pWidgetNode->GetWidgetAcc();
733     if (!pAcc)
734       continue;
735 
736     CFXJSE_Engine* pScriptContext =
737         pWidgetNode->GetDocument()->GetScriptContext();
738     WideString wsRef = item->GetRef();
739     uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
740                        XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent |
741                        XFA_RESOLVENODE_ALL;
742     XFA_RESOLVENODE_RS rs;
743     pScriptContext->ResolveObjects(pWidgetNode, wsRef.AsStringView(), &rs,
744                                    dwStyle, nullptr);
745     pAcc->DeleteItem(-1, false, false);
746     if (rs.dwFlags != XFA_ResolveNode_RSType_Nodes || rs.objects.empty())
747       continue;
748 
749     WideString wsValueRef = item->GetValueRef();
750     WideString wsLabelRef = item->GetLabelRef();
751     const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef;
752     const bool bLabelUseContent = wsLabelRef.IsEmpty() || wsLabelRef == L"$";
753     const bool bValueUseContent = wsValueRef.IsEmpty() || wsValueRef == L"$";
754     WideString wsValue;
755     WideString wsLabel;
756     uint32_t uValueHash = FX_HashCode_GetW(wsValueRef.AsStringView(), false);
757     for (CXFA_Object* refObject : rs.objects) {
758       CXFA_Node* refNode = refObject->AsNode();
759       if (!refNode)
760         continue;
761 
762       if (bValueUseContent) {
763         wsValue = refNode->JSObject()->GetContent(false);
764       } else {
765         CXFA_Node* nodeValue = refNode->GetFirstChildByName(uValueHash);
766         wsValue = nodeValue ? nodeValue->JSObject()->GetContent(false)
767                             : refNode->JSObject()->GetContent(false);
768       }
769 
770       if (!bUseValue) {
771         if (bLabelUseContent) {
772           wsLabel = refNode->JSObject()->GetContent(false);
773         } else {
774           CXFA_Node* nodeLabel =
775               refNode->GetFirstChildByName(wsLabelRef.AsStringView());
776           if (nodeLabel)
777             wsLabel = nodeLabel->JSObject()->GetContent(false);
778         }
779       } else {
780         wsLabel = wsValue;
781       }
782       pAcc->InsertItem(wsLabel, wsValue, false);
783     }
784   }
785   m_BindItems.clear();
786 }
787 
SetChangeMark()788 void CXFA_FFDocView::SetChangeMark() {
789   if (m_iStatus < XFA_DOCVIEW_LAYOUTSTATUS_End)
790     return;
791 
792   m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get());
793 }
794 
GetRootSubform()795 CXFA_Subform* CXFA_FFDocView::GetRootSubform() {
796   CXFA_Node* pFormPacketNode =
797       ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
798   if (!pFormPacketNode)
799     return nullptr;
800 
801   return pFormPacketNode->GetFirstChildByClass<CXFA_Subform>(
802       XFA_Element::Subform);
803 }
804