Home | History | Annotate | Download | only in fxfa
      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 
     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 
     69 CXFA_FFDocView::~CXFA_FFDocView() {
     70   DestroyDocView();
     71 }
     72 
     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 
     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 
    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 
    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 
    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 
    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 
    210 int32_t CXFA_FFDocView::CountPageViews() const {
    211   return m_pXFADocLayout ? m_pXFADocLayout->CountPages() : 0;
    212 }
    213 
    214 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 
    220 CXFA_LayoutProcessor* CXFA_FFDocView::GetXFALayout() const {
    221   return m_pDoc->GetXFADoc()->GetDocLayout();
    222 }
    223 
    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 
    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 
    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 
    313 CXFA_FFWidget* CXFA_FFDocView::GetWidgetForNode(CXFA_Node* node) {
    314   return static_cast<CXFA_FFWidget*>(GetXFALayout()->GetLayoutItem(node));
    315 }
    316 
    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>
    324 CXFA_FFDocView::CreateWidgetAccIterator() {
    325   CXFA_Subform* pFormRoot = GetRootSubform();
    326   return pFormRoot ? pdfium::MakeUnique<CXFA_WidgetAccIterator>(pFormRoot)
    327                    : nullptr;
    328 }
    329 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    543 void CXFA_FFDocView::AddInvalidateRect(CXFA_FFWidget* pWidget,
    544                                        const CFX_RectF& rtInvalidate) {
    545   AddInvalidateRect(pWidget->GetPageView(), rtInvalidate);
    546 }
    547 
    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 
    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 
    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 
    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 
    598 void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) {
    599   m_NewAddedNodes.push_back(pNode);
    600   InitLayout(pNode);
    601 }
    602 
    603 void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Node* pNode) {
    604   ASSERT(pNode->GetElementType() == XFA_Element::Subform);
    605   m_IndexChangedSubforms.push_back(pNode);
    606 }
    607 
    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 
    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 
    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 
    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 
    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 
    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 
    675 void CXFA_FFDocView::AddValidateWidget(CXFA_WidgetAcc* pWidget) {
    676   if (!pdfium::ContainsValue(m_ValidateAccs, pWidget))
    677     m_ValidateAccs.push_back(pWidget);
    678 }
    679 
    680 void CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) {
    681   ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true,
    682                                nullptr);
    683 }
    684 
    685 void CXFA_FFDocView::ProcessValueChanged(CXFA_WidgetAcc* widgetAcc) {
    686   AddValidateWidget(widgetAcc);
    687   AddCalculateWidgetAcc(widgetAcc);
    688   RunCalculateWidgets();
    689   RunValidate();
    690 }
    691 
    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 
    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 
    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 
    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 
    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 
    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