1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2014 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_document.h"
8*3ac0a46fSAndroid Build Coastguard Worker
9*3ac0a46fSAndroid Build Coastguard Worker #include <set>
10*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
11*3ac0a46fSAndroid Build Coastguard Worker
12*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_extension.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/stl_util.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmldocument.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmlelement.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/gc/container_trace.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_engine.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_resolveprocessor.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_object.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check_op.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/notreached.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffdoc.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffnotify.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cscript_datawindow.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cscript_eventpseudomodel.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cscript_hostpseudomodel.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cscript_layoutpseudomodel.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cscript_logpseudomodel.h"
30*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cscript_signaturepseudomodel.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_bind.h"
32*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_datagroup.h"
33*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_exdata.h"
34*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_form.h"
35*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_image.h"
36*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_interactive.h"
37*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_items.h"
38*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_localemgr.h"
39*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_node.h"
40*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_occur.h"
41*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_pageset.h"
42*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_pdf.h"
43*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_present.h"
44*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_subform.h"
45*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_template.h"
46*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h"
47*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
48*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_value.h"
49*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_document_datamerger_imp.h"
50*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_utils.h"
51*3ac0a46fSAndroid Build Coastguard Worker
52*3ac0a46fSAndroid Build Coastguard Worker namespace {
53*3ac0a46fSAndroid Build Coastguard Worker
54*3ac0a46fSAndroid Build Coastguard Worker const wchar_t kTemplateNS[] = L"http://www.xfa.org/schema/xfa-template/";
55*3ac0a46fSAndroid Build Coastguard Worker
56*3ac0a46fSAndroid Build Coastguard Worker struct RecurseRecord {
57*3ac0a46fSAndroid Build Coastguard Worker cppgc::Persistent<CXFA_Node> pTemplateChild;
58*3ac0a46fSAndroid Build Coastguard Worker cppgc::Persistent<CXFA_Node> pDataChild;
59*3ac0a46fSAndroid Build Coastguard Worker };
60*3ac0a46fSAndroid Build Coastguard Worker
61*3ac0a46fSAndroid Build Coastguard Worker class CXFA_TraverseStrategy_DDGroup {
62*3ac0a46fSAndroid Build Coastguard Worker public:
GetFirstChild(CXFA_Node * pDDGroupNode)63*3ac0a46fSAndroid Build Coastguard Worker static CXFA_Node* GetFirstChild(CXFA_Node* pDDGroupNode) {
64*3ac0a46fSAndroid Build Coastguard Worker return pDDGroupNode->GetFirstChildByName(XFA_HASHCODE_Group);
65*3ac0a46fSAndroid Build Coastguard Worker }
GetNextSibling(CXFA_Node * pDDGroupNode)66*3ac0a46fSAndroid Build Coastguard Worker static CXFA_Node* GetNextSibling(CXFA_Node* pDDGroupNode) {
67*3ac0a46fSAndroid Build Coastguard Worker return pDDGroupNode->GetNextSameNameSibling(XFA_HASHCODE_Group);
68*3ac0a46fSAndroid Build Coastguard Worker }
GetParent(CXFA_Node * pDDGroupNode)69*3ac0a46fSAndroid Build Coastguard Worker static CXFA_Node* GetParent(CXFA_Node* pDDGroupNode) {
70*3ac0a46fSAndroid Build Coastguard Worker return pDDGroupNode->GetParent();
71*3ac0a46fSAndroid Build Coastguard Worker }
72*3ac0a46fSAndroid Build Coastguard Worker };
73*3ac0a46fSAndroid Build Coastguard Worker
FormValueNode_MatchNoneCreateChild(CXFA_Node * pFormNode)74*3ac0a46fSAndroid Build Coastguard Worker void FormValueNode_MatchNoneCreateChild(CXFA_Node* pFormNode) {
75*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pFormNode->IsWidgetReady());
76*3ac0a46fSAndroid Build Coastguard Worker // GetUIChildNode has the side effect of creating the UI child.
77*3ac0a46fSAndroid Build Coastguard Worker pFormNode->GetUIChildNode();
78*3ac0a46fSAndroid Build Coastguard Worker }
79*3ac0a46fSAndroid Build Coastguard Worker
FormValueNode_CreateChild(CXFA_Node * pValueNode,XFA_Element iType)80*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* FormValueNode_CreateChild(CXFA_Node* pValueNode, XFA_Element iType) {
81*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pChildNode = pValueNode->GetFirstChild();
82*3ac0a46fSAndroid Build Coastguard Worker if (!pChildNode) {
83*3ac0a46fSAndroid Build Coastguard Worker if (iType == XFA_Element::Unknown)
84*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
85*3ac0a46fSAndroid Build Coastguard Worker
86*3ac0a46fSAndroid Build Coastguard Worker pChildNode =
87*3ac0a46fSAndroid Build Coastguard Worker pValueNode->JSObject()->GetOrCreateProperty<CXFA_Node>(0, iType);
88*3ac0a46fSAndroid Build Coastguard Worker }
89*3ac0a46fSAndroid Build Coastguard Worker return pChildNode;
90*3ac0a46fSAndroid Build Coastguard Worker }
91*3ac0a46fSAndroid Build Coastguard Worker
FormValueNode_SetChildContent(CXFA_Node * pValueNode,const WideString & wsContent,XFA_Element iType)92*3ac0a46fSAndroid Build Coastguard Worker void FormValueNode_SetChildContent(CXFA_Node* pValueNode,
93*3ac0a46fSAndroid Build Coastguard Worker const WideString& wsContent,
94*3ac0a46fSAndroid Build Coastguard Worker XFA_Element iType) {
95*3ac0a46fSAndroid Build Coastguard Worker if (!pValueNode)
96*3ac0a46fSAndroid Build Coastguard Worker return;
97*3ac0a46fSAndroid Build Coastguard Worker
98*3ac0a46fSAndroid Build Coastguard Worker DCHECK_EQ(pValueNode->GetPacketType(), XFA_PacketType::Form);
99*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pChildNode = FormValueNode_CreateChild(pValueNode, iType);
100*3ac0a46fSAndroid Build Coastguard Worker if (!pChildNode)
101*3ac0a46fSAndroid Build Coastguard Worker return;
102*3ac0a46fSAndroid Build Coastguard Worker
103*3ac0a46fSAndroid Build Coastguard Worker switch (pChildNode->GetObjectType()) {
104*3ac0a46fSAndroid Build Coastguard Worker case XFA_ObjectType::ContentNode: {
105*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pContentRawDataNode = pChildNode->GetFirstChild();
106*3ac0a46fSAndroid Build Coastguard Worker if (!pContentRawDataNode) {
107*3ac0a46fSAndroid Build Coastguard Worker XFA_Element element = XFA_Element::Sharptext;
108*3ac0a46fSAndroid Build Coastguard Worker if (pChildNode->GetElementType() == XFA_Element::ExData) {
109*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> contentType =
110*3ac0a46fSAndroid Build Coastguard Worker pChildNode->JSObject()->TryAttribute(XFA_Attribute::ContentType,
111*3ac0a46fSAndroid Build Coastguard Worker false);
112*3ac0a46fSAndroid Build Coastguard Worker if (contentType.has_value()) {
113*3ac0a46fSAndroid Build Coastguard Worker if (contentType.value().EqualsASCII("text/html"))
114*3ac0a46fSAndroid Build Coastguard Worker element = XFA_Element::SharpxHTML;
115*3ac0a46fSAndroid Build Coastguard Worker else if (contentType.value().EqualsASCII("text/xml"))
116*3ac0a46fSAndroid Build Coastguard Worker element = XFA_Element::Sharpxml;
117*3ac0a46fSAndroid Build Coastguard Worker }
118*3ac0a46fSAndroid Build Coastguard Worker }
119*3ac0a46fSAndroid Build Coastguard Worker pContentRawDataNode = pChildNode->CreateSamePacketNode(element);
120*3ac0a46fSAndroid Build Coastguard Worker pChildNode->InsertChildAndNotify(pContentRawDataNode, nullptr);
121*3ac0a46fSAndroid Build Coastguard Worker }
122*3ac0a46fSAndroid Build Coastguard Worker pContentRawDataNode->JSObject()->SetCData(XFA_Attribute::Value,
123*3ac0a46fSAndroid Build Coastguard Worker wsContent);
124*3ac0a46fSAndroid Build Coastguard Worker break;
125*3ac0a46fSAndroid Build Coastguard Worker }
126*3ac0a46fSAndroid Build Coastguard Worker case XFA_ObjectType::NodeC:
127*3ac0a46fSAndroid Build Coastguard Worker case XFA_ObjectType::TextNode:
128*3ac0a46fSAndroid Build Coastguard Worker case XFA_ObjectType::NodeV: {
129*3ac0a46fSAndroid Build Coastguard Worker pChildNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent);
130*3ac0a46fSAndroid Build Coastguard Worker break;
131*3ac0a46fSAndroid Build Coastguard Worker }
132*3ac0a46fSAndroid Build Coastguard Worker default:
133*3ac0a46fSAndroid Build Coastguard Worker break;
134*3ac0a46fSAndroid Build Coastguard Worker }
135*3ac0a46fSAndroid Build Coastguard Worker }
136*3ac0a46fSAndroid Build Coastguard Worker
MergeNodeRecurse(CXFA_Node * pDestNodeParent,CXFA_Node * pProtoNode)137*3ac0a46fSAndroid Build Coastguard Worker void MergeNodeRecurse(CXFA_Node* pDestNodeParent, CXFA_Node* pProtoNode) {
138*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pExistingNode = nullptr;
139*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pFormChild = pDestNodeParent->GetFirstChild(); pFormChild;
140*3ac0a46fSAndroid Build Coastguard Worker pFormChild = pFormChild->GetNextSibling()) {
141*3ac0a46fSAndroid Build Coastguard Worker if (pFormChild->GetElementType() == pProtoNode->GetElementType() &&
142*3ac0a46fSAndroid Build Coastguard Worker pFormChild->GetNameHash() == pProtoNode->GetNameHash() &&
143*3ac0a46fSAndroid Build Coastguard Worker pFormChild->IsUnusedNode()) {
144*3ac0a46fSAndroid Build Coastguard Worker pFormChild->ClearFlag(XFA_NodeFlag::kUnusedNode);
145*3ac0a46fSAndroid Build Coastguard Worker pExistingNode = pFormChild;
146*3ac0a46fSAndroid Build Coastguard Worker break;
147*3ac0a46fSAndroid Build Coastguard Worker }
148*3ac0a46fSAndroid Build Coastguard Worker }
149*3ac0a46fSAndroid Build Coastguard Worker
150*3ac0a46fSAndroid Build Coastguard Worker if (pExistingNode) {
151*3ac0a46fSAndroid Build Coastguard Worker pExistingNode->SetTemplateNode(pProtoNode);
152*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pTemplateChild = pProtoNode->GetFirstChild();
153*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
154*3ac0a46fSAndroid Build Coastguard Worker MergeNodeRecurse(pExistingNode, pTemplateChild);
155*3ac0a46fSAndroid Build Coastguard Worker }
156*3ac0a46fSAndroid Build Coastguard Worker return;
157*3ac0a46fSAndroid Build Coastguard Worker }
158*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNewNode = pProtoNode->Clone(true);
159*3ac0a46fSAndroid Build Coastguard Worker pNewNode->SetTemplateNode(pProtoNode);
160*3ac0a46fSAndroid Build Coastguard Worker pDestNodeParent->InsertChildAndNotify(pNewNode, nullptr);
161*3ac0a46fSAndroid Build Coastguard Worker }
162*3ac0a46fSAndroid Build Coastguard Worker
MergeNode(CXFA_Node * pDestNode,CXFA_Node * pProtoNode)163*3ac0a46fSAndroid Build Coastguard Worker void MergeNode(CXFA_Node* pDestNode, CXFA_Node* pProtoNode) {
164*3ac0a46fSAndroid Build Coastguard Worker {
165*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIterator sIterator(pDestNode);
166*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
167*3ac0a46fSAndroid Build Coastguard Worker pNode = sIterator.MoveToNext()) {
168*3ac0a46fSAndroid Build Coastguard Worker pNode->SetFlag(XFA_NodeFlag::kUnusedNode);
169*3ac0a46fSAndroid Build Coastguard Worker }
170*3ac0a46fSAndroid Build Coastguard Worker }
171*3ac0a46fSAndroid Build Coastguard Worker pDestNode->SetTemplateNode(pProtoNode);
172*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pTemplateChild = pProtoNode->GetFirstChild(); pTemplateChild;
173*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild = pTemplateChild->GetNextSibling()) {
174*3ac0a46fSAndroid Build Coastguard Worker MergeNodeRecurse(pDestNode, pTemplateChild);
175*3ac0a46fSAndroid Build Coastguard Worker }
176*3ac0a46fSAndroid Build Coastguard Worker {
177*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIterator sIterator(pDestNode);
178*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
179*3ac0a46fSAndroid Build Coastguard Worker pNode = sIterator.MoveToNext()) {
180*3ac0a46fSAndroid Build Coastguard Worker pNode->ClearFlag(XFA_NodeFlag::kUnusedNode);
181*3ac0a46fSAndroid Build Coastguard Worker }
182*3ac0a46fSAndroid Build Coastguard Worker }
183*3ac0a46fSAndroid Build Coastguard Worker }
184*3ac0a46fSAndroid Build Coastguard Worker
CloneOrMergeInstanceManager(CXFA_Document * pDocument,CXFA_Node * pFormParent,CXFA_Node * pTemplateNode,std::vector<CXFA_Node * > * subforms)185*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CloneOrMergeInstanceManager(CXFA_Document* pDocument,
186*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFormParent,
187*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pTemplateNode,
188*3ac0a46fSAndroid Build Coastguard Worker std::vector<CXFA_Node*>* subforms) {
189*3ac0a46fSAndroid Build Coastguard Worker WideString wsSubformName =
190*3ac0a46fSAndroid Build Coastguard Worker pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name);
191*3ac0a46fSAndroid Build Coastguard Worker WideString wsInstMgrNodeName = L"_" + wsSubformName;
192*3ac0a46fSAndroid Build Coastguard Worker uint32_t dwInstNameHash = FX_HashCode_GetW(wsInstMgrNodeName.AsStringView());
193*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pExistingNode = XFA_DataMerge_FindFormDOMInstance(
194*3ac0a46fSAndroid Build Coastguard Worker pDocument, XFA_Element::InstanceManager, dwInstNameHash, pFormParent);
195*3ac0a46fSAndroid Build Coastguard Worker if (pExistingNode) {
196*3ac0a46fSAndroid Build Coastguard Worker uint32_t dwNameHash = pTemplateNode->GetNameHash();
197*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pNode = pExistingNode->GetNextSibling(); pNode;) {
198*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eCurType = pNode->GetElementType();
199*3ac0a46fSAndroid Build Coastguard Worker if (eCurType == XFA_Element::InstanceManager)
200*3ac0a46fSAndroid Build Coastguard Worker break;
201*3ac0a46fSAndroid Build Coastguard Worker
202*3ac0a46fSAndroid Build Coastguard Worker if ((eCurType != XFA_Element::Subform) &&
203*3ac0a46fSAndroid Build Coastguard Worker (eCurType != XFA_Element::SubformSet)) {
204*3ac0a46fSAndroid Build Coastguard Worker pNode = pNode->GetNextSibling();
205*3ac0a46fSAndroid Build Coastguard Worker continue;
206*3ac0a46fSAndroid Build Coastguard Worker }
207*3ac0a46fSAndroid Build Coastguard Worker if (dwNameHash != pNode->GetNameHash())
208*3ac0a46fSAndroid Build Coastguard Worker break;
209*3ac0a46fSAndroid Build Coastguard Worker
210*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNextNode = pNode->GetNextSibling();
211*3ac0a46fSAndroid Build Coastguard Worker pFormParent->RemoveChildAndNotify(pNode, true);
212*3ac0a46fSAndroid Build Coastguard Worker subforms->push_back(pNode);
213*3ac0a46fSAndroid Build Coastguard Worker pNode = pNextNode;
214*3ac0a46fSAndroid Build Coastguard Worker }
215*3ac0a46fSAndroid Build Coastguard Worker pFormParent->RemoveChildAndNotify(pExistingNode, true);
216*3ac0a46fSAndroid Build Coastguard Worker pFormParent->InsertChildAndNotify(pExistingNode, nullptr);
217*3ac0a46fSAndroid Build Coastguard Worker pExistingNode->ClearFlag(XFA_NodeFlag::kUnusedNode);
218*3ac0a46fSAndroid Build Coastguard Worker pExistingNode->SetTemplateNode(pTemplateNode);
219*3ac0a46fSAndroid Build Coastguard Worker return pExistingNode;
220*3ac0a46fSAndroid Build Coastguard Worker }
221*3ac0a46fSAndroid Build Coastguard Worker
222*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNewNode =
223*3ac0a46fSAndroid Build Coastguard Worker pDocument->CreateNode(XFA_PacketType::Form, XFA_Element::InstanceManager);
224*3ac0a46fSAndroid Build Coastguard Worker wsInstMgrNodeName =
225*3ac0a46fSAndroid Build Coastguard Worker L"_" + pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name);
226*3ac0a46fSAndroid Build Coastguard Worker pNewNode->JSObject()->SetCData(XFA_Attribute::Name, wsInstMgrNodeName);
227*3ac0a46fSAndroid Build Coastguard Worker pFormParent->InsertChildAndNotify(pNewNode, nullptr);
228*3ac0a46fSAndroid Build Coastguard Worker pNewNode->SetTemplateNode(pTemplateNode);
229*3ac0a46fSAndroid Build Coastguard Worker return pNewNode;
230*3ac0a46fSAndroid Build Coastguard Worker }
231*3ac0a46fSAndroid Build Coastguard Worker
SortRecurseRecord(std::vector<RecurseRecord> * rgRecords,CXFA_Node * pDataScope,bool bChoiceMode)232*3ac0a46fSAndroid Build Coastguard Worker void SortRecurseRecord(std::vector<RecurseRecord>* rgRecords,
233*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataScope,
234*3ac0a46fSAndroid Build Coastguard Worker bool bChoiceMode) {
235*3ac0a46fSAndroid Build Coastguard Worker std::vector<RecurseRecord> rgResultRecord;
236*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pNode = pDataScope->GetFirstChild(); pNode;
237*3ac0a46fSAndroid Build Coastguard Worker pNode = pNode->GetNextSibling()) {
238*3ac0a46fSAndroid Build Coastguard Worker auto it = std::find_if(rgRecords->begin(), rgRecords->end(),
239*3ac0a46fSAndroid Build Coastguard Worker [pNode](const RecurseRecord& record) {
240*3ac0a46fSAndroid Build Coastguard Worker return pNode == record.pDataChild;
241*3ac0a46fSAndroid Build Coastguard Worker });
242*3ac0a46fSAndroid Build Coastguard Worker if (it != rgRecords->end()) {
243*3ac0a46fSAndroid Build Coastguard Worker rgResultRecord.push_back(*it);
244*3ac0a46fSAndroid Build Coastguard Worker rgRecords->erase(it);
245*3ac0a46fSAndroid Build Coastguard Worker if (bChoiceMode)
246*3ac0a46fSAndroid Build Coastguard Worker break;
247*3ac0a46fSAndroid Build Coastguard Worker }
248*3ac0a46fSAndroid Build Coastguard Worker }
249*3ac0a46fSAndroid Build Coastguard Worker if (rgResultRecord.empty())
250*3ac0a46fSAndroid Build Coastguard Worker return;
251*3ac0a46fSAndroid Build Coastguard Worker
252*3ac0a46fSAndroid Build Coastguard Worker if (!bChoiceMode) {
253*3ac0a46fSAndroid Build Coastguard Worker rgResultRecord.insert(rgResultRecord.end(), rgRecords->begin(),
254*3ac0a46fSAndroid Build Coastguard Worker rgRecords->end());
255*3ac0a46fSAndroid Build Coastguard Worker }
256*3ac0a46fSAndroid Build Coastguard Worker *rgRecords = rgResultRecord;
257*3ac0a46fSAndroid Build Coastguard Worker }
258*3ac0a46fSAndroid Build Coastguard Worker
ScopeMatchGlobalBinding(CXFA_Node * pDataScope,uint32_t dwNameHash,XFA_Element eMatchDataNodeType,bool bUpLevel)259*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* ScopeMatchGlobalBinding(CXFA_Node* pDataScope,
260*3ac0a46fSAndroid Build Coastguard Worker uint32_t dwNameHash,
261*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eMatchDataNodeType,
262*3ac0a46fSAndroid Build Coastguard Worker bool bUpLevel) {
263*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node *pCurDataScope = pDataScope, *pLastDataScope = nullptr;
264*3ac0a46fSAndroid Build Coastguard Worker pCurDataScope &&
265*3ac0a46fSAndroid Build Coastguard Worker pCurDataScope->GetPacketType() == XFA_PacketType::Datasets;
266*3ac0a46fSAndroid Build Coastguard Worker pLastDataScope = pCurDataScope,
267*3ac0a46fSAndroid Build Coastguard Worker pCurDataScope = pCurDataScope->GetParent()) {
268*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash);
269*3ac0a46fSAndroid Build Coastguard Worker pDataChild;
270*3ac0a46fSAndroid Build Coastguard Worker pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) {
271*3ac0a46fSAndroid Build Coastguard Worker if (pDataChild == pLastDataScope ||
272*3ac0a46fSAndroid Build Coastguard Worker (eMatchDataNodeType != XFA_Element::DataModel &&
273*3ac0a46fSAndroid Build Coastguard Worker pDataChild->GetElementType() != eMatchDataNodeType) ||
274*3ac0a46fSAndroid Build Coastguard Worker pDataChild->HasBindItem()) {
275*3ac0a46fSAndroid Build Coastguard Worker continue;
276*3ac0a46fSAndroid Build Coastguard Worker }
277*3ac0a46fSAndroid Build Coastguard Worker return pDataChild;
278*3ac0a46fSAndroid Build Coastguard Worker }
279*3ac0a46fSAndroid Build Coastguard Worker
280*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_DataGroup* pDataChild =
281*3ac0a46fSAndroid Build Coastguard Worker pCurDataScope->GetFirstChildByClass<CXFA_DataGroup>(
282*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::DataGroup);
283*3ac0a46fSAndroid Build Coastguard Worker pDataChild;
284*3ac0a46fSAndroid Build Coastguard Worker pDataChild = pDataChild->GetNextSameClassSibling<CXFA_DataGroup>(
285*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::DataGroup)) {
286*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataNode = ScopeMatchGlobalBinding(pDataChild, dwNameHash,
287*3ac0a46fSAndroid Build Coastguard Worker eMatchDataNodeType, false);
288*3ac0a46fSAndroid Build Coastguard Worker if (pDataNode)
289*3ac0a46fSAndroid Build Coastguard Worker return pDataNode;
290*3ac0a46fSAndroid Build Coastguard Worker }
291*3ac0a46fSAndroid Build Coastguard Worker if (!bUpLevel)
292*3ac0a46fSAndroid Build Coastguard Worker break;
293*3ac0a46fSAndroid Build Coastguard Worker }
294*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
295*3ac0a46fSAndroid Build Coastguard Worker }
296*3ac0a46fSAndroid Build Coastguard Worker
FindGlobalDataNode(CXFA_Document * pDocument,const WideString & wsName,CXFA_Node * pDataScope,XFA_Element eMatchNodeType)297*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* FindGlobalDataNode(CXFA_Document* pDocument,
298*3ac0a46fSAndroid Build Coastguard Worker const WideString& wsName,
299*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataScope,
300*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eMatchNodeType) {
301*3ac0a46fSAndroid Build Coastguard Worker if (wsName.IsEmpty())
302*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
303*3ac0a46fSAndroid Build Coastguard Worker
304*3ac0a46fSAndroid Build Coastguard Worker uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView());
305*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pBounded = pDocument->GetGlobalBinding(dwNameHash);
306*3ac0a46fSAndroid Build Coastguard Worker if (!pBounded) {
307*3ac0a46fSAndroid Build Coastguard Worker pBounded =
308*3ac0a46fSAndroid Build Coastguard Worker ScopeMatchGlobalBinding(pDataScope, dwNameHash, eMatchNodeType, true);
309*3ac0a46fSAndroid Build Coastguard Worker if (pBounded)
310*3ac0a46fSAndroid Build Coastguard Worker pDocument->RegisterGlobalBinding(dwNameHash, pBounded);
311*3ac0a46fSAndroid Build Coastguard Worker }
312*3ac0a46fSAndroid Build Coastguard Worker return pBounded;
313*3ac0a46fSAndroid Build Coastguard Worker }
314*3ac0a46fSAndroid Build Coastguard Worker
FindOnceDataNode(const WideString & wsName,CXFA_Node * pDataScope,XFA_Element eMatchNodeType)315*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* FindOnceDataNode(const WideString& wsName,
316*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataScope,
317*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eMatchNodeType) {
318*3ac0a46fSAndroid Build Coastguard Worker if (wsName.IsEmpty())
319*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
320*3ac0a46fSAndroid Build Coastguard Worker
321*3ac0a46fSAndroid Build Coastguard Worker uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView());
322*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pLastDataScope = nullptr;
323*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pCurDataScope = pDataScope;
324*3ac0a46fSAndroid Build Coastguard Worker pCurDataScope &&
325*3ac0a46fSAndroid Build Coastguard Worker pCurDataScope->GetPacketType() == XFA_PacketType::Datasets;
326*3ac0a46fSAndroid Build Coastguard Worker pCurDataScope = pCurDataScope->GetParent()) {
327*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash);
328*3ac0a46fSAndroid Build Coastguard Worker pDataChild;
329*3ac0a46fSAndroid Build Coastguard Worker pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) {
330*3ac0a46fSAndroid Build Coastguard Worker if (pDataChild == pLastDataScope || pDataChild->HasBindItem() ||
331*3ac0a46fSAndroid Build Coastguard Worker (eMatchNodeType != XFA_Element::DataModel &&
332*3ac0a46fSAndroid Build Coastguard Worker pDataChild->GetElementType() != eMatchNodeType)) {
333*3ac0a46fSAndroid Build Coastguard Worker continue;
334*3ac0a46fSAndroid Build Coastguard Worker }
335*3ac0a46fSAndroid Build Coastguard Worker return pDataChild;
336*3ac0a46fSAndroid Build Coastguard Worker }
337*3ac0a46fSAndroid Build Coastguard Worker pLastDataScope = pCurDataScope;
338*3ac0a46fSAndroid Build Coastguard Worker }
339*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
340*3ac0a46fSAndroid Build Coastguard Worker }
341*3ac0a46fSAndroid Build Coastguard Worker
FindDataRefDataNode(CXFA_Document * pDocument,const WideString & wsRef,CXFA_Node * pDataScope,XFA_Element eMatchNodeType,CXFA_Node * pTemplateNode,bool bForceBind,bool bUpLevel)342*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* FindDataRefDataNode(CXFA_Document* pDocument,
343*3ac0a46fSAndroid Build Coastguard Worker const WideString& wsRef,
344*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataScope,
345*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eMatchNodeType,
346*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pTemplateNode,
347*3ac0a46fSAndroid Build Coastguard Worker bool bForceBind,
348*3ac0a46fSAndroid Build Coastguard Worker bool bUpLevel) {
349*3ac0a46fSAndroid Build Coastguard Worker Mask<XFA_ResolveFlag> dwFlags = {XFA_ResolveFlag::kChildren,
350*3ac0a46fSAndroid Build Coastguard Worker XFA_ResolveFlag::kBindNew};
351*3ac0a46fSAndroid Build Coastguard Worker if (bUpLevel || !wsRef.EqualsASCII("name")) {
352*3ac0a46fSAndroid Build Coastguard Worker dwFlags |= XFA_ResolveFlag::kParent;
353*3ac0a46fSAndroid Build Coastguard Worker dwFlags |= XFA_ResolveFlag::kSiblings;
354*3ac0a46fSAndroid Build Coastguard Worker }
355*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
356*3ac0a46fSAndroid Build Coastguard Worker pDocument->GetScriptContext()->ResolveObjectsWithBindNode(
357*3ac0a46fSAndroid Build Coastguard Worker pDataScope, wsRef.AsStringView(), dwFlags, pTemplateNode);
358*3ac0a46fSAndroid Build Coastguard Worker if (!maybeResult.has_value())
359*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
360*3ac0a46fSAndroid Build Coastguard Worker
361*3ac0a46fSAndroid Build Coastguard Worker if (maybeResult.value().type ==
362*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::ResolveResult::Type::kCreateNodeAll ||
363*3ac0a46fSAndroid Build Coastguard Worker maybeResult.value().type ==
364*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::ResolveResult::Type::kCreateNodeMidAll ||
365*3ac0a46fSAndroid Build Coastguard Worker maybeResult.value().objects.size() > 1) {
366*3ac0a46fSAndroid Build Coastguard Worker return pDocument->GetNotBindNode(maybeResult.value().objects);
367*3ac0a46fSAndroid Build Coastguard Worker }
368*3ac0a46fSAndroid Build Coastguard Worker
369*3ac0a46fSAndroid Build Coastguard Worker if (maybeResult.value().type ==
370*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::ResolveResult::Type::kCreateNodeOne) {
371*3ac0a46fSAndroid Build Coastguard Worker CXFA_Object* pObject = !maybeResult.value().objects.empty()
372*3ac0a46fSAndroid Build Coastguard Worker ? maybeResult.value().objects.front().Get()
373*3ac0a46fSAndroid Build Coastguard Worker : nullptr;
374*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNode = ToNode(pObject);
375*3ac0a46fSAndroid Build Coastguard Worker return (bForceBind || !pNode || !pNode->HasBindItem()) ? pNode : nullptr;
376*3ac0a46fSAndroid Build Coastguard Worker }
377*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
378*3ac0a46fSAndroid Build Coastguard Worker }
379*3ac0a46fSAndroid Build Coastguard Worker
FindMatchingDataNode(CXFA_Document * pDocument,CXFA_Node * pTemplateNode,CXFA_Node * pDataScope,bool & bAccessedDataDOM,bool bForceBind,CXFA_NodeIteratorTemplate<CXFA_Node,CXFA_TraverseStrategy_XFAContainerNode> * pIterator,bool & bSelfMatch,XFA_AttributeValue & eBindMatch,bool bUpLevel)380*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* FindMatchingDataNode(
381*3ac0a46fSAndroid Build Coastguard Worker CXFA_Document* pDocument,
382*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pTemplateNode,
383*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataScope,
384*3ac0a46fSAndroid Build Coastguard Worker bool& bAccessedDataDOM,
385*3ac0a46fSAndroid Build Coastguard Worker bool bForceBind,
386*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIteratorTemplate<CXFA_Node,
387*3ac0a46fSAndroid Build Coastguard Worker CXFA_TraverseStrategy_XFAContainerNode>*
388*3ac0a46fSAndroid Build Coastguard Worker pIterator,
389*3ac0a46fSAndroid Build Coastguard Worker bool& bSelfMatch,
390*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue& eBindMatch,
391*3ac0a46fSAndroid Build Coastguard Worker bool bUpLevel) {
392*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pResult = nullptr;
393*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pCurTemplateNode = pIterator->GetCurrent();
394*3ac0a46fSAndroid Build Coastguard Worker while (pCurTemplateNode) {
395*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eMatchNodeType;
396*3ac0a46fSAndroid Build Coastguard Worker switch (pCurTemplateNode->GetElementType()) {
397*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::Subform:
398*3ac0a46fSAndroid Build Coastguard Worker eMatchNodeType = XFA_Element::DataGroup;
399*3ac0a46fSAndroid Build Coastguard Worker break;
400*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::Field: {
401*3ac0a46fSAndroid Build Coastguard Worker eMatchNodeType = XFA_FieldIsMultiListBox(pCurTemplateNode)
402*3ac0a46fSAndroid Build Coastguard Worker ? XFA_Element::DataGroup
403*3ac0a46fSAndroid Build Coastguard Worker : XFA_Element::DataValue;
404*3ac0a46fSAndroid Build Coastguard Worker } break;
405*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::ExclGroup:
406*3ac0a46fSAndroid Build Coastguard Worker eMatchNodeType = XFA_Element::DataValue;
407*3ac0a46fSAndroid Build Coastguard Worker break;
408*3ac0a46fSAndroid Build Coastguard Worker default:
409*3ac0a46fSAndroid Build Coastguard Worker pCurTemplateNode = pIterator->MoveToNext();
410*3ac0a46fSAndroid Build Coastguard Worker continue;
411*3ac0a46fSAndroid Build Coastguard Worker }
412*3ac0a46fSAndroid Build Coastguard Worker
413*3ac0a46fSAndroid Build Coastguard Worker CXFA_Occur* pTemplateNodeOccur =
414*3ac0a46fSAndroid Build Coastguard Worker pCurTemplateNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur);
415*3ac0a46fSAndroid Build Coastguard Worker if (pTemplateNodeOccur) {
416*3ac0a46fSAndroid Build Coastguard Worker int32_t iMin;
417*3ac0a46fSAndroid Build Coastguard Worker int32_t iMax;
418*3ac0a46fSAndroid Build Coastguard Worker int32_t iInit;
419*3ac0a46fSAndroid Build Coastguard Worker std::tie(iMin, iMax, iInit) = pTemplateNodeOccur->GetOccurInfo();
420*3ac0a46fSAndroid Build Coastguard Worker if (iMax == 0) {
421*3ac0a46fSAndroid Build Coastguard Worker pCurTemplateNode = pIterator->MoveToNext();
422*3ac0a46fSAndroid Build Coastguard Worker continue;
423*3ac0a46fSAndroid Build Coastguard Worker }
424*3ac0a46fSAndroid Build Coastguard Worker }
425*3ac0a46fSAndroid Build Coastguard Worker
426*3ac0a46fSAndroid Build Coastguard Worker CXFA_Bind* pTemplateNodeBind =
427*3ac0a46fSAndroid Build Coastguard Worker pCurTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind);
428*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue eMatch =
429*3ac0a46fSAndroid Build Coastguard Worker pTemplateNodeBind
430*3ac0a46fSAndroid Build Coastguard Worker ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match)
431*3ac0a46fSAndroid Build Coastguard Worker : XFA_AttributeValue::Once;
432*3ac0a46fSAndroid Build Coastguard Worker eBindMatch = eMatch;
433*3ac0a46fSAndroid Build Coastguard Worker switch (eMatch) {
434*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::None:
435*3ac0a46fSAndroid Build Coastguard Worker pCurTemplateNode = pIterator->MoveToNext();
436*3ac0a46fSAndroid Build Coastguard Worker continue;
437*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::Global:
438*3ac0a46fSAndroid Build Coastguard Worker bAccessedDataDOM = true;
439*3ac0a46fSAndroid Build Coastguard Worker if (!bForceBind) {
440*3ac0a46fSAndroid Build Coastguard Worker pCurTemplateNode = pIterator->MoveToNext();
441*3ac0a46fSAndroid Build Coastguard Worker continue;
442*3ac0a46fSAndroid Build Coastguard Worker }
443*3ac0a46fSAndroid Build Coastguard Worker if (eMatchNodeType == XFA_Element::DataValue ||
444*3ac0a46fSAndroid Build Coastguard Worker (eMatchNodeType == XFA_Element::DataGroup &&
445*3ac0a46fSAndroid Build Coastguard Worker XFA_FieldIsMultiListBox(pTemplateNodeBind))) {
446*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pGlobalBindNode = FindGlobalDataNode(
447*3ac0a46fSAndroid Build Coastguard Worker pDocument,
448*3ac0a46fSAndroid Build Coastguard Worker pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name),
449*3ac0a46fSAndroid Build Coastguard Worker pDataScope, eMatchNodeType);
450*3ac0a46fSAndroid Build Coastguard Worker if (!pGlobalBindNode) {
451*3ac0a46fSAndroid Build Coastguard Worker pCurTemplateNode = pIterator->MoveToNext();
452*3ac0a46fSAndroid Build Coastguard Worker continue;
453*3ac0a46fSAndroid Build Coastguard Worker }
454*3ac0a46fSAndroid Build Coastguard Worker pResult = pGlobalBindNode;
455*3ac0a46fSAndroid Build Coastguard Worker break;
456*3ac0a46fSAndroid Build Coastguard Worker }
457*3ac0a46fSAndroid Build Coastguard Worker [[fallthrough]];
458*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::Once: {
459*3ac0a46fSAndroid Build Coastguard Worker bAccessedDataDOM = true;
460*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pOnceBindNode = FindOnceDataNode(
461*3ac0a46fSAndroid Build Coastguard Worker pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name),
462*3ac0a46fSAndroid Build Coastguard Worker pDataScope, eMatchNodeType);
463*3ac0a46fSAndroid Build Coastguard Worker if (!pOnceBindNode) {
464*3ac0a46fSAndroid Build Coastguard Worker pCurTemplateNode = pIterator->MoveToNext();
465*3ac0a46fSAndroid Build Coastguard Worker continue;
466*3ac0a46fSAndroid Build Coastguard Worker }
467*3ac0a46fSAndroid Build Coastguard Worker pResult = pOnceBindNode;
468*3ac0a46fSAndroid Build Coastguard Worker break;
469*3ac0a46fSAndroid Build Coastguard Worker }
470*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::DataRef: {
471*3ac0a46fSAndroid Build Coastguard Worker bAccessedDataDOM = true;
472*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataRefBindNode = FindDataRefDataNode(
473*3ac0a46fSAndroid Build Coastguard Worker pDocument,
474*3ac0a46fSAndroid Build Coastguard Worker pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref),
475*3ac0a46fSAndroid Build Coastguard Worker pDataScope, eMatchNodeType, pTemplateNode, bForceBind, bUpLevel);
476*3ac0a46fSAndroid Build Coastguard Worker if (pDataRefBindNode &&
477*3ac0a46fSAndroid Build Coastguard Worker pDataRefBindNode->GetElementType() == eMatchNodeType) {
478*3ac0a46fSAndroid Build Coastguard Worker pResult = pDataRefBindNode;
479*3ac0a46fSAndroid Build Coastguard Worker }
480*3ac0a46fSAndroid Build Coastguard Worker if (!pResult) {
481*3ac0a46fSAndroid Build Coastguard Worker pCurTemplateNode = pIterator->SkipChildrenAndMoveToNext();
482*3ac0a46fSAndroid Build Coastguard Worker continue;
483*3ac0a46fSAndroid Build Coastguard Worker }
484*3ac0a46fSAndroid Build Coastguard Worker break;
485*3ac0a46fSAndroid Build Coastguard Worker }
486*3ac0a46fSAndroid Build Coastguard Worker default:
487*3ac0a46fSAndroid Build Coastguard Worker break;
488*3ac0a46fSAndroid Build Coastguard Worker }
489*3ac0a46fSAndroid Build Coastguard Worker if (pCurTemplateNode == pTemplateNode && pResult)
490*3ac0a46fSAndroid Build Coastguard Worker bSelfMatch = true;
491*3ac0a46fSAndroid Build Coastguard Worker break;
492*3ac0a46fSAndroid Build Coastguard Worker }
493*3ac0a46fSAndroid Build Coastguard Worker return pResult;
494*3ac0a46fSAndroid Build Coastguard Worker }
495*3ac0a46fSAndroid Build Coastguard Worker
CreateDataBinding(CXFA_Node * pFormNode,CXFA_Node * pDataNode,bool bDataToForm)496*3ac0a46fSAndroid Build Coastguard Worker void CreateDataBinding(CXFA_Node* pFormNode,
497*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataNode,
498*3ac0a46fSAndroid Build Coastguard Worker bool bDataToForm) {
499*3ac0a46fSAndroid Build Coastguard Worker pFormNode->SetBindingNode(pDataNode);
500*3ac0a46fSAndroid Build Coastguard Worker pDataNode->AddBindItem(pFormNode);
501*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eType = pFormNode->GetElementType();
502*3ac0a46fSAndroid Build Coastguard Worker if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup)
503*3ac0a46fSAndroid Build Coastguard Worker return;
504*3ac0a46fSAndroid Build Coastguard Worker
505*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pFormNode->IsWidgetReady());
506*3ac0a46fSAndroid Build Coastguard Worker auto* defValue = pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>(
507*3ac0a46fSAndroid Build Coastguard Worker 0, XFA_Element::Value);
508*3ac0a46fSAndroid Build Coastguard Worker if (!bDataToForm) {
509*3ac0a46fSAndroid Build Coastguard Worker WideString wsValue;
510*3ac0a46fSAndroid Build Coastguard Worker switch (pFormNode->GetFFWidgetType()) {
511*3ac0a46fSAndroid Build Coastguard Worker case XFA_FFWidgetType::kImageEdit: {
512*3ac0a46fSAndroid Build Coastguard Worker CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr;
513*3ac0a46fSAndroid Build Coastguard Worker WideString wsContentType;
514*3ac0a46fSAndroid Build Coastguard Worker WideString wsHref;
515*3ac0a46fSAndroid Build Coastguard Worker if (image) {
516*3ac0a46fSAndroid Build Coastguard Worker wsValue = image->GetContent();
517*3ac0a46fSAndroid Build Coastguard Worker wsContentType = image->GetContentType();
518*3ac0a46fSAndroid Build Coastguard Worker wsHref = image->GetHref();
519*3ac0a46fSAndroid Build Coastguard Worker }
520*3ac0a46fSAndroid Build Coastguard Worker CFX_XMLElement* pXMLDataElement =
521*3ac0a46fSAndroid Build Coastguard Worker ToXMLElement(pDataNode->GetXMLMappingNode());
522*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pXMLDataElement);
523*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetAttributeValue(
524*3ac0a46fSAndroid Build Coastguard Worker wsValue, pFormNode->GetFormatDataValue(wsValue));
525*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType,
526*3ac0a46fSAndroid Build Coastguard Worker wsContentType);
527*3ac0a46fSAndroid Build Coastguard Worker if (!wsHref.IsEmpty())
528*3ac0a46fSAndroid Build Coastguard Worker pXMLDataElement->SetAttribute(L"href", wsHref);
529*3ac0a46fSAndroid Build Coastguard Worker
530*3ac0a46fSAndroid Build Coastguard Worker break;
531*3ac0a46fSAndroid Build Coastguard Worker }
532*3ac0a46fSAndroid Build Coastguard Worker case XFA_FFWidgetType::kChoiceList:
533*3ac0a46fSAndroid Build Coastguard Worker wsValue = defValue ? defValue->GetChildValueContent() : WideString();
534*3ac0a46fSAndroid Build Coastguard Worker if (pFormNode->IsChoiceListMultiSelect()) {
535*3ac0a46fSAndroid Build Coastguard Worker std::vector<WideString> wsSelTextArray =
536*3ac0a46fSAndroid Build Coastguard Worker pFormNode->GetSelectedItemsValue();
537*3ac0a46fSAndroid Build Coastguard Worker if (!wsSelTextArray.empty()) {
538*3ac0a46fSAndroid Build Coastguard Worker for (const auto& text : wsSelTextArray) {
539*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pValue =
540*3ac0a46fSAndroid Build Coastguard Worker pDataNode->CreateSamePacketNode(XFA_Element::DataValue);
541*3ac0a46fSAndroid Build Coastguard Worker pValue->JSObject()->SetCData(XFA_Attribute::Name, L"value");
542*3ac0a46fSAndroid Build Coastguard Worker pValue->CreateXMLMappingNode();
543*3ac0a46fSAndroid Build Coastguard Worker pDataNode->InsertChildAndNotify(pValue, nullptr);
544*3ac0a46fSAndroid Build Coastguard Worker pValue->JSObject()->SetCData(XFA_Attribute::Value, text);
545*3ac0a46fSAndroid Build Coastguard Worker }
546*3ac0a46fSAndroid Build Coastguard Worker } else {
547*3ac0a46fSAndroid Build Coastguard Worker CFX_XMLElement* pElement =
548*3ac0a46fSAndroid Build Coastguard Worker ToXMLElement(pDataNode->GetXMLMappingNode());
549*3ac0a46fSAndroid Build Coastguard Worker pElement->SetAttribute(L"xfa:dataNode", L"dataGroup");
550*3ac0a46fSAndroid Build Coastguard Worker }
551*3ac0a46fSAndroid Build Coastguard Worker } else if (!wsValue.IsEmpty()) {
552*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetAttributeValue(
553*3ac0a46fSAndroid Build Coastguard Worker wsValue, pFormNode->GetFormatDataValue(wsValue));
554*3ac0a46fSAndroid Build Coastguard Worker }
555*3ac0a46fSAndroid Build Coastguard Worker break;
556*3ac0a46fSAndroid Build Coastguard Worker case XFA_FFWidgetType::kCheckButton:
557*3ac0a46fSAndroid Build Coastguard Worker wsValue = defValue ? defValue->GetChildValueContent() : WideString();
558*3ac0a46fSAndroid Build Coastguard Worker if (wsValue.IsEmpty())
559*3ac0a46fSAndroid Build Coastguard Worker break;
560*3ac0a46fSAndroid Build Coastguard Worker
561*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetAttributeValue(
562*3ac0a46fSAndroid Build Coastguard Worker wsValue, pFormNode->GetFormatDataValue(wsValue));
563*3ac0a46fSAndroid Build Coastguard Worker break;
564*3ac0a46fSAndroid Build Coastguard Worker case XFA_FFWidgetType::kExclGroup: {
565*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pChecked = nullptr;
566*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pChild = pFormNode->GetFirstChild();
567*3ac0a46fSAndroid Build Coastguard Worker for (; pChild; pChild = pChild->GetNextSibling()) {
568*3ac0a46fSAndroid Build Coastguard Worker if (pChild->GetElementType() != XFA_Element::Field)
569*3ac0a46fSAndroid Build Coastguard Worker continue;
570*3ac0a46fSAndroid Build Coastguard Worker
571*3ac0a46fSAndroid Build Coastguard Worker auto* pValue =
572*3ac0a46fSAndroid Build Coastguard Worker pChild->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
573*3ac0a46fSAndroid Build Coastguard Worker if (!pValue)
574*3ac0a46fSAndroid Build Coastguard Worker continue;
575*3ac0a46fSAndroid Build Coastguard Worker
576*3ac0a46fSAndroid Build Coastguard Worker wsValue = pValue->GetChildValueContent();
577*3ac0a46fSAndroid Build Coastguard Worker if (wsValue.IsEmpty())
578*3ac0a46fSAndroid Build Coastguard Worker continue;
579*3ac0a46fSAndroid Build Coastguard Worker
580*3ac0a46fSAndroid Build Coastguard Worker CXFA_Items* pItems =
581*3ac0a46fSAndroid Build Coastguard Worker pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
582*3ac0a46fSAndroid Build Coastguard Worker if (!pItems)
583*3ac0a46fSAndroid Build Coastguard Worker continue;
584*3ac0a46fSAndroid Build Coastguard Worker
585*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pText = pItems->GetFirstChild();
586*3ac0a46fSAndroid Build Coastguard Worker if (!pText)
587*3ac0a46fSAndroid Build Coastguard Worker continue;
588*3ac0a46fSAndroid Build Coastguard Worker
589*3ac0a46fSAndroid Build Coastguard Worker WideString wsContent = pText->JSObject()->GetContent(false);
590*3ac0a46fSAndroid Build Coastguard Worker if (wsContent == wsValue) {
591*3ac0a46fSAndroid Build Coastguard Worker pChecked = pChild;
592*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetAttributeValue(wsValue, wsValue);
593*3ac0a46fSAndroid Build Coastguard Worker pFormNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent);
594*3ac0a46fSAndroid Build Coastguard Worker break;
595*3ac0a46fSAndroid Build Coastguard Worker }
596*3ac0a46fSAndroid Build Coastguard Worker }
597*3ac0a46fSAndroid Build Coastguard Worker if (!pChecked)
598*3ac0a46fSAndroid Build Coastguard Worker break;
599*3ac0a46fSAndroid Build Coastguard Worker
600*3ac0a46fSAndroid Build Coastguard Worker pChild = pFormNode->GetFirstChild();
601*3ac0a46fSAndroid Build Coastguard Worker for (; pChild; pChild = pChild->GetNextSibling()) {
602*3ac0a46fSAndroid Build Coastguard Worker if (pChild == pChecked)
603*3ac0a46fSAndroid Build Coastguard Worker continue;
604*3ac0a46fSAndroid Build Coastguard Worker if (pChild->GetElementType() != XFA_Element::Field)
605*3ac0a46fSAndroid Build Coastguard Worker continue;
606*3ac0a46fSAndroid Build Coastguard Worker
607*3ac0a46fSAndroid Build Coastguard Worker CXFA_Value* pValue =
608*3ac0a46fSAndroid Build Coastguard Worker pChild->JSObject()->GetOrCreateProperty<CXFA_Value>(
609*3ac0a46fSAndroid Build Coastguard Worker 0, XFA_Element::Value);
610*3ac0a46fSAndroid Build Coastguard Worker CXFA_Items* pItems =
611*3ac0a46fSAndroid Build Coastguard Worker pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
612*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pText = pItems ? pItems->GetFirstChild() : nullptr;
613*3ac0a46fSAndroid Build Coastguard Worker if (pText)
614*3ac0a46fSAndroid Build Coastguard Worker pText = pText->GetNextSibling();
615*3ac0a46fSAndroid Build Coastguard Worker
616*3ac0a46fSAndroid Build Coastguard Worker WideString wsContent;
617*3ac0a46fSAndroid Build Coastguard Worker if (pText)
618*3ac0a46fSAndroid Build Coastguard Worker wsContent = pText->JSObject()->GetContent(false);
619*3ac0a46fSAndroid Build Coastguard Worker
620*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_SetChildContent(pValue, wsContent, XFA_Element::Text);
621*3ac0a46fSAndroid Build Coastguard Worker }
622*3ac0a46fSAndroid Build Coastguard Worker break;
623*3ac0a46fSAndroid Build Coastguard Worker }
624*3ac0a46fSAndroid Build Coastguard Worker case XFA_FFWidgetType::kNumericEdit: {
625*3ac0a46fSAndroid Build Coastguard Worker wsValue = defValue ? defValue->GetChildValueContent() : WideString();
626*3ac0a46fSAndroid Build Coastguard Worker if (wsValue.IsEmpty())
627*3ac0a46fSAndroid Build Coastguard Worker break;
628*3ac0a46fSAndroid Build Coastguard Worker
629*3ac0a46fSAndroid Build Coastguard Worker wsValue = pFormNode->NormalizeNumStr(wsValue);
630*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetAttributeValue(
631*3ac0a46fSAndroid Build Coastguard Worker wsValue, pFormNode->GetFormatDataValue(wsValue));
632*3ac0a46fSAndroid Build Coastguard Worker CXFA_Value* pValue =
633*3ac0a46fSAndroid Build Coastguard Worker pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>(
634*3ac0a46fSAndroid Build Coastguard Worker 0, XFA_Element::Value);
635*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_SetChildContent(pValue, wsValue, XFA_Element::Float);
636*3ac0a46fSAndroid Build Coastguard Worker break;
637*3ac0a46fSAndroid Build Coastguard Worker }
638*3ac0a46fSAndroid Build Coastguard Worker default:
639*3ac0a46fSAndroid Build Coastguard Worker wsValue = defValue ? defValue->GetChildValueContent() : WideString();
640*3ac0a46fSAndroid Build Coastguard Worker if (wsValue.IsEmpty())
641*3ac0a46fSAndroid Build Coastguard Worker break;
642*3ac0a46fSAndroid Build Coastguard Worker
643*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetAttributeValue(
644*3ac0a46fSAndroid Build Coastguard Worker wsValue, pFormNode->GetFormatDataValue(wsValue));
645*3ac0a46fSAndroid Build Coastguard Worker break;
646*3ac0a46fSAndroid Build Coastguard Worker }
647*3ac0a46fSAndroid Build Coastguard Worker return;
648*3ac0a46fSAndroid Build Coastguard Worker }
649*3ac0a46fSAndroid Build Coastguard Worker
650*3ac0a46fSAndroid Build Coastguard Worker WideString wsXMLValue = pDataNode->JSObject()->GetContent(false);
651*3ac0a46fSAndroid Build Coastguard Worker WideString wsNormalizeValue = pFormNode->GetNormalizeDataValue(wsXMLValue);
652*3ac0a46fSAndroid Build Coastguard Worker
653*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetAttributeValue(wsNormalizeValue, wsXMLValue);
654*3ac0a46fSAndroid Build Coastguard Worker switch (pFormNode->GetFFWidgetType()) {
655*3ac0a46fSAndroid Build Coastguard Worker case XFA_FFWidgetType::kImageEdit: {
656*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_SetChildContent(defValue, wsNormalizeValue,
657*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::Image);
658*3ac0a46fSAndroid Build Coastguard Worker CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr;
659*3ac0a46fSAndroid Build Coastguard Worker if (image) {
660*3ac0a46fSAndroid Build Coastguard Worker CFX_XMLElement* pXMLDataElement =
661*3ac0a46fSAndroid Build Coastguard Worker ToXMLElement(pDataNode->GetXMLMappingNode());
662*3ac0a46fSAndroid Build Coastguard Worker WideString wsContentType =
663*3ac0a46fSAndroid Build Coastguard Worker pXMLDataElement->GetAttribute(L"xfa:contentType");
664*3ac0a46fSAndroid Build Coastguard Worker if (!wsContentType.IsEmpty()) {
665*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType,
666*3ac0a46fSAndroid Build Coastguard Worker wsContentType);
667*3ac0a46fSAndroid Build Coastguard Worker image->SetContentType(wsContentType);
668*3ac0a46fSAndroid Build Coastguard Worker }
669*3ac0a46fSAndroid Build Coastguard Worker
670*3ac0a46fSAndroid Build Coastguard Worker WideString wsHref = pXMLDataElement->GetAttribute(L"href");
671*3ac0a46fSAndroid Build Coastguard Worker if (!wsHref.IsEmpty())
672*3ac0a46fSAndroid Build Coastguard Worker image->SetHref(wsHref);
673*3ac0a46fSAndroid Build Coastguard Worker }
674*3ac0a46fSAndroid Build Coastguard Worker break;
675*3ac0a46fSAndroid Build Coastguard Worker }
676*3ac0a46fSAndroid Build Coastguard Worker case XFA_FFWidgetType::kChoiceList:
677*3ac0a46fSAndroid Build Coastguard Worker if (pFormNode->IsChoiceListMultiSelect()) {
678*3ac0a46fSAndroid Build Coastguard Worker std::vector<CXFA_Node*> items = pDataNode->GetNodeListWithFilter(
679*3ac0a46fSAndroid Build Coastguard Worker {XFA_NodeFilter::kChildren, XFA_NodeFilter::kProperties});
680*3ac0a46fSAndroid Build Coastguard Worker if (!items.empty()) {
681*3ac0a46fSAndroid Build Coastguard Worker bool single = items.size() == 1;
682*3ac0a46fSAndroid Build Coastguard Worker wsNormalizeValue.clear();
683*3ac0a46fSAndroid Build Coastguard Worker
684*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pNode : items) {
685*3ac0a46fSAndroid Build Coastguard Worker WideString wsItem = pNode->JSObject()->GetContent(false);
686*3ac0a46fSAndroid Build Coastguard Worker if (single)
687*3ac0a46fSAndroid Build Coastguard Worker wsItem += L"\n";
688*3ac0a46fSAndroid Build Coastguard Worker
689*3ac0a46fSAndroid Build Coastguard Worker wsNormalizeValue += wsItem;
690*3ac0a46fSAndroid Build Coastguard Worker }
691*3ac0a46fSAndroid Build Coastguard Worker CXFA_ExData* exData =
692*3ac0a46fSAndroid Build Coastguard Worker defValue ? defValue->GetExDataIfExists() : nullptr;
693*3ac0a46fSAndroid Build Coastguard Worker if (exData)
694*3ac0a46fSAndroid Build Coastguard Worker exData->SetContentType(single ? L"text/plain" : L"text/xml");
695*3ac0a46fSAndroid Build Coastguard Worker }
696*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_SetChildContent(defValue, wsNormalizeValue,
697*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::ExData);
698*3ac0a46fSAndroid Build Coastguard Worker } else {
699*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_SetChildContent(defValue, wsNormalizeValue,
700*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::Text);
701*3ac0a46fSAndroid Build Coastguard Worker }
702*3ac0a46fSAndroid Build Coastguard Worker break;
703*3ac0a46fSAndroid Build Coastguard Worker case XFA_FFWidgetType::kExclGroup: {
704*3ac0a46fSAndroid Build Coastguard Worker pFormNode->SetSelectedMemberByValue(wsNormalizeValue.AsStringView(),
705*3ac0a46fSAndroid Build Coastguard Worker false, false, false);
706*3ac0a46fSAndroid Build Coastguard Worker break;
707*3ac0a46fSAndroid Build Coastguard Worker }
708*3ac0a46fSAndroid Build Coastguard Worker case XFA_FFWidgetType::kDateTimeEdit:
709*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_SetChildContent(defValue, wsNormalizeValue,
710*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::DateTime);
711*3ac0a46fSAndroid Build Coastguard Worker break;
712*3ac0a46fSAndroid Build Coastguard Worker case XFA_FFWidgetType::kNumericEdit: {
713*3ac0a46fSAndroid Build Coastguard Worker WideString wsPicture =
714*3ac0a46fSAndroid Build Coastguard Worker pFormNode->GetPictureContent(XFA_ValuePicture::kDataBind);
715*3ac0a46fSAndroid Build Coastguard Worker if (wsPicture.IsEmpty())
716*3ac0a46fSAndroid Build Coastguard Worker wsNormalizeValue = pFormNode->NormalizeNumStr(wsNormalizeValue);
717*3ac0a46fSAndroid Build Coastguard Worker
718*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_SetChildContent(defValue, wsNormalizeValue,
719*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::Float);
720*3ac0a46fSAndroid Build Coastguard Worker break;
721*3ac0a46fSAndroid Build Coastguard Worker }
722*3ac0a46fSAndroid Build Coastguard Worker default:
723*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_SetChildContent(defValue, wsNormalizeValue,
724*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::Text);
725*3ac0a46fSAndroid Build Coastguard Worker break;
726*3ac0a46fSAndroid Build Coastguard Worker }
727*3ac0a46fSAndroid Build Coastguard Worker }
728*3ac0a46fSAndroid Build Coastguard Worker
MaybeCreateDataNode(CXFA_Document * pDocument,CXFA_Node * pDataParent,XFA_Element eNodeType,const WideString & wsName)729*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* MaybeCreateDataNode(CXFA_Document* pDocument,
730*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataParent,
731*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eNodeType,
732*3ac0a46fSAndroid Build Coastguard Worker const WideString& wsName) {
733*3ac0a46fSAndroid Build Coastguard Worker if (!pDataParent)
734*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
735*3ac0a46fSAndroid Build Coastguard Worker
736*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pParentDDNode = pDataParent->GetDataDescriptionNode();
737*3ac0a46fSAndroid Build Coastguard Worker if (!pParentDDNode) {
738*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataNode =
739*3ac0a46fSAndroid Build Coastguard Worker pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType);
740*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName);
741*3ac0a46fSAndroid Build Coastguard Worker pDataNode->CreateXMLMappingNode();
742*3ac0a46fSAndroid Build Coastguard Worker pDataParent->InsertChildAndNotify(pDataNode, nullptr);
743*3ac0a46fSAndroid Build Coastguard Worker pDataNode->SetFlag(XFA_NodeFlag::kInitialized);
744*3ac0a46fSAndroid Build Coastguard Worker return pDataNode;
745*3ac0a46fSAndroid Build Coastguard Worker }
746*3ac0a46fSAndroid Build Coastguard Worker
747*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup> sIterator(
748*3ac0a46fSAndroid Build Coastguard Worker pParentDDNode);
749*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
750*3ac0a46fSAndroid Build Coastguard Worker pDDGroupNode = sIterator.MoveToNext()) {
751*3ac0a46fSAndroid Build Coastguard Worker if (pDDGroupNode != pParentDDNode) {
752*3ac0a46fSAndroid Build Coastguard Worker if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup)
753*3ac0a46fSAndroid Build Coastguard Worker continue;
754*3ac0a46fSAndroid Build Coastguard Worker
755*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace();
756*3ac0a46fSAndroid Build Coastguard Worker if (!ns.has_value() ||
757*3ac0a46fSAndroid Build Coastguard Worker !ns.value().EqualsASCII("http://ns.adobe.com/data-description/")) {
758*3ac0a46fSAndroid Build Coastguard Worker continue;
759*3ac0a46fSAndroid Build Coastguard Worker }
760*3ac0a46fSAndroid Build Coastguard Worker }
761*3ac0a46fSAndroid Build Coastguard Worker
762*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDDNode =
763*3ac0a46fSAndroid Build Coastguard Worker pDDGroupNode->GetFirstChildByName(wsName.AsStringView());
764*3ac0a46fSAndroid Build Coastguard Worker if (!pDDNode)
765*3ac0a46fSAndroid Build Coastguard Worker continue;
766*3ac0a46fSAndroid Build Coastguard Worker if (pDDNode->GetElementType() != eNodeType)
767*3ac0a46fSAndroid Build Coastguard Worker break;
768*3ac0a46fSAndroid Build Coastguard Worker
769*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataNode =
770*3ac0a46fSAndroid Build Coastguard Worker pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType);
771*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName);
772*3ac0a46fSAndroid Build Coastguard Worker pDataNode->CreateXMLMappingNode();
773*3ac0a46fSAndroid Build Coastguard Worker if (eNodeType == XFA_Element::DataValue &&
774*3ac0a46fSAndroid Build Coastguard Worker pDDNode->JSObject()->GetEnum(XFA_Attribute::Contains) ==
775*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::MetaData) {
776*3ac0a46fSAndroid Build Coastguard Worker pDataNode->JSObject()->SetEnum(XFA_Attribute::Contains,
777*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::MetaData, false);
778*3ac0a46fSAndroid Build Coastguard Worker }
779*3ac0a46fSAndroid Build Coastguard Worker pDataParent->InsertChildAndNotify(pDataNode, nullptr);
780*3ac0a46fSAndroid Build Coastguard Worker pDataNode->SetDataDescriptionNode(pDDNode);
781*3ac0a46fSAndroid Build Coastguard Worker pDataNode->SetFlag(XFA_NodeFlag::kInitialized);
782*3ac0a46fSAndroid Build Coastguard Worker return pDataNode;
783*3ac0a46fSAndroid Build Coastguard Worker }
784*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
785*3ac0a46fSAndroid Build Coastguard Worker }
786*3ac0a46fSAndroid Build Coastguard Worker
CopyContainer_Field(CXFA_Document * pDocument,CXFA_Node * pTemplateNode,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bDataMerge,bool bUpLevel)787*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CopyContainer_Field(CXFA_Document* pDocument,
788*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pTemplateNode,
789*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFormNode,
790*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataScope,
791*3ac0a46fSAndroid Build Coastguard Worker bool bDataMerge,
792*3ac0a46fSAndroid Build Coastguard Worker bool bUpLevel) {
793*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFieldNode = XFA_NodeMerge_CloneOrMergeContainer(
794*3ac0a46fSAndroid Build Coastguard Worker pDocument, pFormNode, pTemplateNode, false, nullptr);
795*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pFieldNode);
796*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pTemplateChildNode = pTemplateNode->GetFirstChild();
797*3ac0a46fSAndroid Build Coastguard Worker pTemplateChildNode;
798*3ac0a46fSAndroid Build Coastguard Worker pTemplateChildNode = pTemplateChildNode->GetNextSibling()) {
799*3ac0a46fSAndroid Build Coastguard Worker if (XFA_DataMerge_NeedGenerateForm(pTemplateChildNode, true)) {
800*3ac0a46fSAndroid Build Coastguard Worker XFA_NodeMerge_CloneOrMergeContainer(pDocument, pFieldNode,
801*3ac0a46fSAndroid Build Coastguard Worker pTemplateChildNode, true, nullptr);
802*3ac0a46fSAndroid Build Coastguard Worker } else if (pTemplateNode->GetElementType() == XFA_Element::ExclGroup &&
803*3ac0a46fSAndroid Build Coastguard Worker pTemplateChildNode->IsContainerNode()) {
804*3ac0a46fSAndroid Build Coastguard Worker if (pTemplateChildNode->GetElementType() == XFA_Element::Field) {
805*3ac0a46fSAndroid Build Coastguard Worker CopyContainer_Field(pDocument, pTemplateChildNode, pFieldNode, nullptr,
806*3ac0a46fSAndroid Build Coastguard Worker false, true);
807*3ac0a46fSAndroid Build Coastguard Worker }
808*3ac0a46fSAndroid Build Coastguard Worker }
809*3ac0a46fSAndroid Build Coastguard Worker }
810*3ac0a46fSAndroid Build Coastguard Worker if (bDataMerge) {
811*3ac0a46fSAndroid Build Coastguard Worker bool bAccessedDataDOM = false;
812*3ac0a46fSAndroid Build Coastguard Worker bool bSelfMatch = false;
813*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue eBindMatch;
814*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode>
815*3ac0a46fSAndroid Build Coastguard Worker sNodeIter(pTemplateNode);
816*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataNode = FindMatchingDataNode(
817*3ac0a46fSAndroid Build Coastguard Worker pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, true,
818*3ac0a46fSAndroid Build Coastguard Worker &sNodeIter, bSelfMatch, eBindMatch, bUpLevel);
819*3ac0a46fSAndroid Build Coastguard Worker if (pDataNode)
820*3ac0a46fSAndroid Build Coastguard Worker CreateDataBinding(pFieldNode, pDataNode, true);
821*3ac0a46fSAndroid Build Coastguard Worker } else {
822*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_MatchNoneCreateChild(pFieldNode);
823*3ac0a46fSAndroid Build Coastguard Worker }
824*3ac0a46fSAndroid Build Coastguard Worker return pFieldNode;
825*3ac0a46fSAndroid Build Coastguard Worker }
826*3ac0a46fSAndroid Build Coastguard Worker
CopyContainer_SubformSet(CXFA_Document * pDocument,CXFA_Node * pTemplateNode,CXFA_Node * pFormParentNode,CXFA_Node * pDataScope,bool bOneInstance,bool bDataMerge)827*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument,
828*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pTemplateNode,
829*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFormParentNode,
830*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataScope,
831*3ac0a46fSAndroid Build Coastguard Worker bool bOneInstance,
832*3ac0a46fSAndroid Build Coastguard Worker bool bDataMerge) {
833*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eType = pTemplateNode->GetElementType();
834*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pOccurNode = nullptr;
835*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFirstInstance = nullptr;
836*3ac0a46fSAndroid Build Coastguard Worker bool bUseInstanceManager =
837*3ac0a46fSAndroid Build Coastguard Worker pFormParentNode->GetElementType() != XFA_Element::Area;
838*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pInstMgrNode = nullptr;
839*3ac0a46fSAndroid Build Coastguard Worker std::vector<CXFA_Node*> subformArray;
840*3ac0a46fSAndroid Build Coastguard Worker std::vector<CXFA_Node*>* pSearchArray = nullptr;
841*3ac0a46fSAndroid Build Coastguard Worker if (!bOneInstance &&
842*3ac0a46fSAndroid Build Coastguard Worker (eType == XFA_Element::SubformSet || eType == XFA_Element::Subform)) {
843*3ac0a46fSAndroid Build Coastguard Worker pInstMgrNode = bUseInstanceManager ? CloneOrMergeInstanceManager(
844*3ac0a46fSAndroid Build Coastguard Worker pDocument, pFormParentNode,
845*3ac0a46fSAndroid Build Coastguard Worker pTemplateNode, &subformArray)
846*3ac0a46fSAndroid Build Coastguard Worker : nullptr;
847*3ac0a46fSAndroid Build Coastguard Worker if (CXFA_Occur* pOccurTemplateNode =
848*3ac0a46fSAndroid Build Coastguard Worker pTemplateNode->GetFirstChildByClass<CXFA_Occur>(
849*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::Occur)) {
850*3ac0a46fSAndroid Build Coastguard Worker pOccurNode = pInstMgrNode ? XFA_NodeMerge_CloneOrMergeContainer(
851*3ac0a46fSAndroid Build Coastguard Worker pDocument, pInstMgrNode,
852*3ac0a46fSAndroid Build Coastguard Worker pOccurTemplateNode, false, nullptr)
853*3ac0a46fSAndroid Build Coastguard Worker : pOccurTemplateNode;
854*3ac0a46fSAndroid Build Coastguard Worker } else if (pInstMgrNode) {
855*3ac0a46fSAndroid Build Coastguard Worker pOccurNode =
856*3ac0a46fSAndroid Build Coastguard Worker pInstMgrNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur);
857*3ac0a46fSAndroid Build Coastguard Worker if (pOccurNode)
858*3ac0a46fSAndroid Build Coastguard Worker pOccurNode->ClearFlag(XFA_NodeFlag::kUnusedNode);
859*3ac0a46fSAndroid Build Coastguard Worker }
860*3ac0a46fSAndroid Build Coastguard Worker if (pInstMgrNode) {
861*3ac0a46fSAndroid Build Coastguard Worker pInstMgrNode->SetInitializedFlagAndNotify();
862*3ac0a46fSAndroid Build Coastguard Worker pSearchArray = &subformArray;
863*3ac0a46fSAndroid Build Coastguard Worker if (pFormParentNode->GetElementType() == XFA_Element::PageArea) {
864*3ac0a46fSAndroid Build Coastguard Worker bOneInstance = true;
865*3ac0a46fSAndroid Build Coastguard Worker if (subformArray.empty())
866*3ac0a46fSAndroid Build Coastguard Worker pSearchArray = nullptr;
867*3ac0a46fSAndroid Build Coastguard Worker } else if (pTemplateNode->GetNameHash() == 0 && subformArray.empty()) {
868*3ac0a46fSAndroid Build Coastguard Worker pSearchArray = nullptr;
869*3ac0a46fSAndroid Build Coastguard Worker }
870*3ac0a46fSAndroid Build Coastguard Worker }
871*3ac0a46fSAndroid Build Coastguard Worker }
872*3ac0a46fSAndroid Build Coastguard Worker
873*3ac0a46fSAndroid Build Coastguard Worker int32_t iMax = 1;
874*3ac0a46fSAndroid Build Coastguard Worker int32_t iInit = 1;
875*3ac0a46fSAndroid Build Coastguard Worker int32_t iMin = 1;
876*3ac0a46fSAndroid Build Coastguard Worker if (!bOneInstance && pOccurNode) {
877*3ac0a46fSAndroid Build Coastguard Worker std::tie(iMin, iMax, iInit) =
878*3ac0a46fSAndroid Build Coastguard Worker static_cast<CXFA_Occur*>(pOccurNode)->GetOccurInfo();
879*3ac0a46fSAndroid Build Coastguard Worker }
880*3ac0a46fSAndroid Build Coastguard Worker
881*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue eRelation =
882*3ac0a46fSAndroid Build Coastguard Worker eType == XFA_Element::SubformSet
883*3ac0a46fSAndroid Build Coastguard Worker ? pTemplateNode->JSObject()->GetEnum(XFA_Attribute::Relation)
884*3ac0a46fSAndroid Build Coastguard Worker : XFA_AttributeValue::Ordered;
885*3ac0a46fSAndroid Build Coastguard Worker int32_t iCurRepeatIndex = 0;
886*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue eParentBindMatch = XFA_AttributeValue::None;
887*3ac0a46fSAndroid Build Coastguard Worker if (bDataMerge) {
888*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode>
889*3ac0a46fSAndroid Build Coastguard Worker sNodeIterator(pTemplateNode);
890*3ac0a46fSAndroid Build Coastguard Worker bool bAccessedDataDOM = false;
891*3ac0a46fSAndroid Build Coastguard Worker if (eType == XFA_Element::SubformSet || eType == XFA_Element::Area) {
892*3ac0a46fSAndroid Build Coastguard Worker sNodeIterator.MoveToNext();
893*3ac0a46fSAndroid Build Coastguard Worker } else {
894*3ac0a46fSAndroid Build Coastguard Worker std::map<CXFA_Node*, CXFA_Node*> subformMapArray;
895*3ac0a46fSAndroid Build Coastguard Worker std::vector<CXFA_Node*> nodeArray;
896*3ac0a46fSAndroid Build Coastguard Worker for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) {
897*3ac0a46fSAndroid Build Coastguard Worker bool bSelfMatch = false;
898*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue eBindMatch = XFA_AttributeValue::None;
899*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataNode = FindMatchingDataNode(
900*3ac0a46fSAndroid Build Coastguard Worker pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, false,
901*3ac0a46fSAndroid Build Coastguard Worker &sNodeIterator, bSelfMatch, eBindMatch, true);
902*3ac0a46fSAndroid Build Coastguard Worker if (!pDataNode || sNodeIterator.GetCurrent() != pTemplateNode)
903*3ac0a46fSAndroid Build Coastguard Worker break;
904*3ac0a46fSAndroid Build Coastguard Worker
905*3ac0a46fSAndroid Build Coastguard Worker eParentBindMatch = eBindMatch;
906*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pSubformNode = XFA_NodeMerge_CloneOrMergeContainer(
907*3ac0a46fSAndroid Build Coastguard Worker pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
908*3ac0a46fSAndroid Build Coastguard Worker if (!pFirstInstance)
909*3ac0a46fSAndroid Build Coastguard Worker pFirstInstance = pSubformNode;
910*3ac0a46fSAndroid Build Coastguard Worker
911*3ac0a46fSAndroid Build Coastguard Worker CreateDataBinding(pSubformNode, pDataNode, true);
912*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pSubformNode);
913*3ac0a46fSAndroid Build Coastguard Worker subformMapArray[pSubformNode] = pDataNode;
914*3ac0a46fSAndroid Build Coastguard Worker nodeArray.push_back(pSubformNode);
915*3ac0a46fSAndroid Build Coastguard Worker }
916*3ac0a46fSAndroid Build Coastguard Worker
917*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pSubform : nodeArray) {
918*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataNode = nullptr;
919*3ac0a46fSAndroid Build Coastguard Worker auto it = subformMapArray.find(pSubform);
920*3ac0a46fSAndroid Build Coastguard Worker if (it != subformMapArray.end())
921*3ac0a46fSAndroid Build Coastguard Worker pDataNode = it->second;
922*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
923*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild;
924*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild = pTemplateChild->GetNextSibling()) {
925*3ac0a46fSAndroid Build Coastguard Worker if (XFA_DataMerge_NeedGenerateForm(pTemplateChild,
926*3ac0a46fSAndroid Build Coastguard Worker bUseInstanceManager)) {
927*3ac0a46fSAndroid Build Coastguard Worker XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubform,
928*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild, true, nullptr);
929*3ac0a46fSAndroid Build Coastguard Worker } else if (pTemplateChild->IsContainerNode()) {
930*3ac0a46fSAndroid Build Coastguard Worker pDocument->DataMerge_CopyContainer(pTemplateChild, pSubform,
931*3ac0a46fSAndroid Build Coastguard Worker pDataNode, false, true, false);
932*3ac0a46fSAndroid Build Coastguard Worker }
933*3ac0a46fSAndroid Build Coastguard Worker }
934*3ac0a46fSAndroid Build Coastguard Worker }
935*3ac0a46fSAndroid Build Coastguard Worker subformMapArray.clear();
936*3ac0a46fSAndroid Build Coastguard Worker }
937*3ac0a46fSAndroid Build Coastguard Worker
938*3ac0a46fSAndroid Build Coastguard Worker for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) {
939*3ac0a46fSAndroid Build Coastguard Worker bool bSelfMatch = false;
940*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue eBindMatch = XFA_AttributeValue::None;
941*3ac0a46fSAndroid Build Coastguard Worker if (!FindMatchingDataNode(pDocument, pTemplateNode, pDataScope,
942*3ac0a46fSAndroid Build Coastguard Worker bAccessedDataDOM, false, &sNodeIterator,
943*3ac0a46fSAndroid Build Coastguard Worker bSelfMatch, eBindMatch, true)) {
944*3ac0a46fSAndroid Build Coastguard Worker break;
945*3ac0a46fSAndroid Build Coastguard Worker }
946*3ac0a46fSAndroid Build Coastguard Worker if (eBindMatch == XFA_AttributeValue::DataRef &&
947*3ac0a46fSAndroid Build Coastguard Worker eParentBindMatch == XFA_AttributeValue::DataRef) {
948*3ac0a46fSAndroid Build Coastguard Worker break;
949*3ac0a46fSAndroid Build Coastguard Worker }
950*3ac0a46fSAndroid Build Coastguard Worker
951*3ac0a46fSAndroid Build Coastguard Worker if (eRelation == XFA_AttributeValue::Choice ||
952*3ac0a46fSAndroid Build Coastguard Worker eRelation == XFA_AttributeValue::Unordered) {
953*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
954*3ac0a46fSAndroid Build Coastguard Worker pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
955*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pSubformSetNode);
956*3ac0a46fSAndroid Build Coastguard Worker if (!pFirstInstance)
957*3ac0a46fSAndroid Build Coastguard Worker pFirstInstance = pSubformSetNode;
958*3ac0a46fSAndroid Build Coastguard Worker
959*3ac0a46fSAndroid Build Coastguard Worker std::vector<RecurseRecord> rgItemMatchList;
960*3ac0a46fSAndroid Build Coastguard Worker std::vector<CXFA_Node*> rgItemUnmatchList;
961*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
962*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild;
963*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild = pTemplateChild->GetNextSibling()) {
964*3ac0a46fSAndroid Build Coastguard Worker if (XFA_DataMerge_NeedGenerateForm(pTemplateChild,
965*3ac0a46fSAndroid Build Coastguard Worker bUseInstanceManager)) {
966*3ac0a46fSAndroid Build Coastguard Worker XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
967*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild, true, nullptr);
968*3ac0a46fSAndroid Build Coastguard Worker } else if (pTemplateChild->IsContainerNode()) {
969*3ac0a46fSAndroid Build Coastguard Worker bSelfMatch = false;
970*3ac0a46fSAndroid Build Coastguard Worker eBindMatch = XFA_AttributeValue::None;
971*3ac0a46fSAndroid Build Coastguard Worker if (eRelation != XFA_AttributeValue::Ordered) {
972*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIteratorTemplate<CXFA_Node,
973*3ac0a46fSAndroid Build Coastguard Worker CXFA_TraverseStrategy_XFAContainerNode>
974*3ac0a46fSAndroid Build Coastguard Worker sChildIter(pTemplateChild);
975*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataMatch = FindMatchingDataNode(
976*3ac0a46fSAndroid Build Coastguard Worker pDocument, pTemplateChild, pDataScope, bAccessedDataDOM,
977*3ac0a46fSAndroid Build Coastguard Worker false, &sChildIter, bSelfMatch, eBindMatch, true);
978*3ac0a46fSAndroid Build Coastguard Worker if (pDataMatch) {
979*3ac0a46fSAndroid Build Coastguard Worker RecurseRecord sNewRecord = {pTemplateChild, pDataMatch};
980*3ac0a46fSAndroid Build Coastguard Worker if (bSelfMatch)
981*3ac0a46fSAndroid Build Coastguard Worker rgItemMatchList.insert(rgItemMatchList.begin(), sNewRecord);
982*3ac0a46fSAndroid Build Coastguard Worker else
983*3ac0a46fSAndroid Build Coastguard Worker rgItemMatchList.push_back(sNewRecord);
984*3ac0a46fSAndroid Build Coastguard Worker } else {
985*3ac0a46fSAndroid Build Coastguard Worker rgItemUnmatchList.push_back(pTemplateChild);
986*3ac0a46fSAndroid Build Coastguard Worker }
987*3ac0a46fSAndroid Build Coastguard Worker } else {
988*3ac0a46fSAndroid Build Coastguard Worker rgItemUnmatchList.push_back(pTemplateChild);
989*3ac0a46fSAndroid Build Coastguard Worker }
990*3ac0a46fSAndroid Build Coastguard Worker }
991*3ac0a46fSAndroid Build Coastguard Worker }
992*3ac0a46fSAndroid Build Coastguard Worker
993*3ac0a46fSAndroid Build Coastguard Worker switch (eRelation) {
994*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::Choice: {
995*3ac0a46fSAndroid Build Coastguard Worker DCHECK(!rgItemMatchList.empty());
996*3ac0a46fSAndroid Build Coastguard Worker SortRecurseRecord(&rgItemMatchList, pDataScope, true);
997*3ac0a46fSAndroid Build Coastguard Worker pDocument->DataMerge_CopyContainer(
998*3ac0a46fSAndroid Build Coastguard Worker rgItemMatchList.front().pTemplateChild, pSubformSetNode,
999*3ac0a46fSAndroid Build Coastguard Worker pDataScope, false, true, true);
1000*3ac0a46fSAndroid Build Coastguard Worker break;
1001*3ac0a46fSAndroid Build Coastguard Worker }
1002*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::Unordered: {
1003*3ac0a46fSAndroid Build Coastguard Worker if (!rgItemMatchList.empty()) {
1004*3ac0a46fSAndroid Build Coastguard Worker SortRecurseRecord(&rgItemMatchList, pDataScope, false);
1005*3ac0a46fSAndroid Build Coastguard Worker for (const auto& matched : rgItemMatchList) {
1006*3ac0a46fSAndroid Build Coastguard Worker pDocument->DataMerge_CopyContainer(matched.pTemplateChild,
1007*3ac0a46fSAndroid Build Coastguard Worker pSubformSetNode, pDataScope,
1008*3ac0a46fSAndroid Build Coastguard Worker false, true, true);
1009*3ac0a46fSAndroid Build Coastguard Worker }
1010*3ac0a46fSAndroid Build Coastguard Worker }
1011*3ac0a46fSAndroid Build Coastguard Worker for (auto* unmatched : rgItemUnmatchList) {
1012*3ac0a46fSAndroid Build Coastguard Worker pDocument->DataMerge_CopyContainer(unmatched, pSubformSetNode,
1013*3ac0a46fSAndroid Build Coastguard Worker pDataScope, false, true, true);
1014*3ac0a46fSAndroid Build Coastguard Worker }
1015*3ac0a46fSAndroid Build Coastguard Worker break;
1016*3ac0a46fSAndroid Build Coastguard Worker }
1017*3ac0a46fSAndroid Build Coastguard Worker default:
1018*3ac0a46fSAndroid Build Coastguard Worker break;
1019*3ac0a46fSAndroid Build Coastguard Worker }
1020*3ac0a46fSAndroid Build Coastguard Worker } else {
1021*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
1022*3ac0a46fSAndroid Build Coastguard Worker pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
1023*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pSubformSetNode);
1024*3ac0a46fSAndroid Build Coastguard Worker if (!pFirstInstance)
1025*3ac0a46fSAndroid Build Coastguard Worker pFirstInstance = pSubformSetNode;
1026*3ac0a46fSAndroid Build Coastguard Worker
1027*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
1028*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild;
1029*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild = pTemplateChild->GetNextSibling()) {
1030*3ac0a46fSAndroid Build Coastguard Worker if (XFA_DataMerge_NeedGenerateForm(pTemplateChild,
1031*3ac0a46fSAndroid Build Coastguard Worker bUseInstanceManager)) {
1032*3ac0a46fSAndroid Build Coastguard Worker XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
1033*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild, true, nullptr);
1034*3ac0a46fSAndroid Build Coastguard Worker } else if (pTemplateChild->IsContainerNode()) {
1035*3ac0a46fSAndroid Build Coastguard Worker pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformSetNode,
1036*3ac0a46fSAndroid Build Coastguard Worker pDataScope, false, true, true);
1037*3ac0a46fSAndroid Build Coastguard Worker }
1038*3ac0a46fSAndroid Build Coastguard Worker }
1039*3ac0a46fSAndroid Build Coastguard Worker }
1040*3ac0a46fSAndroid Build Coastguard Worker }
1041*3ac0a46fSAndroid Build Coastguard Worker
1042*3ac0a46fSAndroid Build Coastguard Worker if (iCurRepeatIndex == 0 && !bAccessedDataDOM) {
1043*3ac0a46fSAndroid Build Coastguard Worker int32_t iLimit = iMax;
1044*3ac0a46fSAndroid Build Coastguard Worker if (pInstMgrNode && pTemplateNode->GetNameHash() == 0) {
1045*3ac0a46fSAndroid Build Coastguard Worker iLimit = fxcrt::CollectionSize<int32_t>(subformArray);
1046*3ac0a46fSAndroid Build Coastguard Worker if (iLimit < iMin)
1047*3ac0a46fSAndroid Build Coastguard Worker iLimit = iInit;
1048*3ac0a46fSAndroid Build Coastguard Worker }
1049*3ac0a46fSAndroid Build Coastguard Worker
1050*3ac0a46fSAndroid Build Coastguard Worker for (; (iLimit < 0 || iCurRepeatIndex < iLimit); iCurRepeatIndex++) {
1051*3ac0a46fSAndroid Build Coastguard Worker if (pInstMgrNode) {
1052*3ac0a46fSAndroid Build Coastguard Worker if (pSearchArray && pSearchArray->empty()) {
1053*3ac0a46fSAndroid Build Coastguard Worker if (pTemplateNode->GetNameHash() != 0)
1054*3ac0a46fSAndroid Build Coastguard Worker break;
1055*3ac0a46fSAndroid Build Coastguard Worker pSearchArray = nullptr;
1056*3ac0a46fSAndroid Build Coastguard Worker }
1057*3ac0a46fSAndroid Build Coastguard Worker } else if (!XFA_DataMerge_FindFormDOMInstance(
1058*3ac0a46fSAndroid Build Coastguard Worker pDocument, pTemplateNode->GetElementType(),
1059*3ac0a46fSAndroid Build Coastguard Worker pTemplateNode->GetNameHash(), pFormParentNode)) {
1060*3ac0a46fSAndroid Build Coastguard Worker break;
1061*3ac0a46fSAndroid Build Coastguard Worker }
1062*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pSubformNode = XFA_NodeMerge_CloneOrMergeContainer(
1063*3ac0a46fSAndroid Build Coastguard Worker pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
1064*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pSubformNode);
1065*3ac0a46fSAndroid Build Coastguard Worker if (!pFirstInstance)
1066*3ac0a46fSAndroid Build Coastguard Worker pFirstInstance = pSubformNode;
1067*3ac0a46fSAndroid Build Coastguard Worker
1068*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
1069*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild;
1070*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild = pTemplateChild->GetNextSibling()) {
1071*3ac0a46fSAndroid Build Coastguard Worker if (XFA_DataMerge_NeedGenerateForm(pTemplateChild,
1072*3ac0a46fSAndroid Build Coastguard Worker bUseInstanceManager)) {
1073*3ac0a46fSAndroid Build Coastguard Worker XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformNode,
1074*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild, true, nullptr);
1075*3ac0a46fSAndroid Build Coastguard Worker } else if (pTemplateChild->IsContainerNode()) {
1076*3ac0a46fSAndroid Build Coastguard Worker pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformNode,
1077*3ac0a46fSAndroid Build Coastguard Worker pDataScope, false, true, true);
1078*3ac0a46fSAndroid Build Coastguard Worker }
1079*3ac0a46fSAndroid Build Coastguard Worker }
1080*3ac0a46fSAndroid Build Coastguard Worker }
1081*3ac0a46fSAndroid Build Coastguard Worker }
1082*3ac0a46fSAndroid Build Coastguard Worker }
1083*3ac0a46fSAndroid Build Coastguard Worker
1084*3ac0a46fSAndroid Build Coastguard Worker int32_t iMinimalLimit = iCurRepeatIndex == 0 ? iInit : iMin;
1085*3ac0a46fSAndroid Build Coastguard Worker for (; iCurRepeatIndex < iMinimalLimit; iCurRepeatIndex++) {
1086*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
1087*3ac0a46fSAndroid Build Coastguard Worker pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
1088*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pSubformSetNode);
1089*3ac0a46fSAndroid Build Coastguard Worker if (!pFirstInstance)
1090*3ac0a46fSAndroid Build Coastguard Worker pFirstInstance = pSubformSetNode;
1091*3ac0a46fSAndroid Build Coastguard Worker
1092*3ac0a46fSAndroid Build Coastguard Worker bool bFound = false;
1093*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
1094*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
1095*3ac0a46fSAndroid Build Coastguard Worker if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
1096*3ac0a46fSAndroid Build Coastguard Worker XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
1097*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild, true, nullptr);
1098*3ac0a46fSAndroid Build Coastguard Worker } else if (pTemplateChild->IsContainerNode()) {
1099*3ac0a46fSAndroid Build Coastguard Worker if (bFound && eRelation == XFA_AttributeValue::Choice)
1100*3ac0a46fSAndroid Build Coastguard Worker continue;
1101*3ac0a46fSAndroid Build Coastguard Worker
1102*3ac0a46fSAndroid Build Coastguard Worker pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformSetNode,
1103*3ac0a46fSAndroid Build Coastguard Worker pDataScope, false, bDataMerge, true);
1104*3ac0a46fSAndroid Build Coastguard Worker bFound = true;
1105*3ac0a46fSAndroid Build Coastguard Worker }
1106*3ac0a46fSAndroid Build Coastguard Worker }
1107*3ac0a46fSAndroid Build Coastguard Worker }
1108*3ac0a46fSAndroid Build Coastguard Worker return pFirstInstance;
1109*3ac0a46fSAndroid Build Coastguard Worker }
1110*3ac0a46fSAndroid Build Coastguard Worker
UpdateBindingRelations(CXFA_Document * pDocument,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bDataRef,bool bParentDataRef)1111*3ac0a46fSAndroid Build Coastguard Worker void UpdateBindingRelations(CXFA_Document* pDocument,
1112*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFormNode,
1113*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataScope,
1114*3ac0a46fSAndroid Build Coastguard Worker bool bDataRef,
1115*3ac0a46fSAndroid Build Coastguard Worker bool bParentDataRef) {
1116*3ac0a46fSAndroid Build Coastguard Worker bool bMatchRef = true;
1117*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eType = pFormNode->GetElementType();
1118*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataNode = pFormNode->GetBindData();
1119*3ac0a46fSAndroid Build Coastguard Worker if (eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup ||
1120*3ac0a46fSAndroid Build Coastguard Worker eType == XFA_Element::Field) {
1121*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pTemplateNode = pFormNode->GetTemplateNodeIfExists();
1122*3ac0a46fSAndroid Build Coastguard Worker CXFA_Bind* pTemplateNodeBind =
1123*3ac0a46fSAndroid Build Coastguard Worker pTemplateNode
1124*3ac0a46fSAndroid Build Coastguard Worker ? pTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind)
1125*3ac0a46fSAndroid Build Coastguard Worker : nullptr;
1126*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue eMatch =
1127*3ac0a46fSAndroid Build Coastguard Worker pTemplateNodeBind
1128*3ac0a46fSAndroid Build Coastguard Worker ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match)
1129*3ac0a46fSAndroid Build Coastguard Worker : XFA_AttributeValue::Once;
1130*3ac0a46fSAndroid Build Coastguard Worker switch (eMatch) {
1131*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::None:
1132*3ac0a46fSAndroid Build Coastguard Worker if (!bDataRef || bParentDataRef)
1133*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_MatchNoneCreateChild(pFormNode);
1134*3ac0a46fSAndroid Build Coastguard Worker break;
1135*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::Once:
1136*3ac0a46fSAndroid Build Coastguard Worker if (!bDataRef || bParentDataRef) {
1137*3ac0a46fSAndroid Build Coastguard Worker if (!pDataNode) {
1138*3ac0a46fSAndroid Build Coastguard Worker if (pFormNode->GetNameHash() != 0 &&
1139*3ac0a46fSAndroid Build Coastguard Worker pFormNode->JSObject()->GetEnum(XFA_Attribute::Scope) !=
1140*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::None) {
1141*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eDataNodeType = (eType == XFA_Element::Subform ||
1142*3ac0a46fSAndroid Build Coastguard Worker XFA_FieldIsMultiListBox(pFormNode))
1143*3ac0a46fSAndroid Build Coastguard Worker ? XFA_Element::DataGroup
1144*3ac0a46fSAndroid Build Coastguard Worker : XFA_Element::DataValue;
1145*3ac0a46fSAndroid Build Coastguard Worker pDataNode = MaybeCreateDataNode(
1146*3ac0a46fSAndroid Build Coastguard Worker pDocument, pDataScope, eDataNodeType,
1147*3ac0a46fSAndroid Build Coastguard Worker WideString(
1148*3ac0a46fSAndroid Build Coastguard Worker pFormNode->JSObject()->GetCData(XFA_Attribute::Name)));
1149*3ac0a46fSAndroid Build Coastguard Worker if (pDataNode)
1150*3ac0a46fSAndroid Build Coastguard Worker CreateDataBinding(pFormNode, pDataNode, false);
1151*3ac0a46fSAndroid Build Coastguard Worker }
1152*3ac0a46fSAndroid Build Coastguard Worker if (!pDataNode)
1153*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_MatchNoneCreateChild(pFormNode);
1154*3ac0a46fSAndroid Build Coastguard Worker
1155*3ac0a46fSAndroid Build Coastguard Worker } else {
1156*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataParent = pDataNode->GetParent();
1157*3ac0a46fSAndroid Build Coastguard Worker if (pDataParent != pDataScope) {
1158*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pDataParent);
1159*3ac0a46fSAndroid Build Coastguard Worker pDataParent->RemoveChildAndNotify(pDataNode, true);
1160*3ac0a46fSAndroid Build Coastguard Worker pDataScope->InsertChildAndNotify(pDataNode, nullptr);
1161*3ac0a46fSAndroid Build Coastguard Worker }
1162*3ac0a46fSAndroid Build Coastguard Worker }
1163*3ac0a46fSAndroid Build Coastguard Worker }
1164*3ac0a46fSAndroid Build Coastguard Worker break;
1165*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::Global:
1166*3ac0a46fSAndroid Build Coastguard Worker if (!bDataRef || bParentDataRef) {
1167*3ac0a46fSAndroid Build Coastguard Worker uint32_t dwNameHash = pFormNode->GetNameHash();
1168*3ac0a46fSAndroid Build Coastguard Worker if (dwNameHash != 0 && !pDataNode) {
1169*3ac0a46fSAndroid Build Coastguard Worker pDataNode = pDocument->GetGlobalBinding(dwNameHash);
1170*3ac0a46fSAndroid Build Coastguard Worker if (!pDataNode) {
1171*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eDataNodeType = (eType == XFA_Element::Subform ||
1172*3ac0a46fSAndroid Build Coastguard Worker XFA_FieldIsMultiListBox(pFormNode))
1173*3ac0a46fSAndroid Build Coastguard Worker ? XFA_Element::DataGroup
1174*3ac0a46fSAndroid Build Coastguard Worker : XFA_Element::DataValue;
1175*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pRecordNode =
1176*3ac0a46fSAndroid Build Coastguard Worker ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record));
1177*3ac0a46fSAndroid Build Coastguard Worker pDataNode = MaybeCreateDataNode(
1178*3ac0a46fSAndroid Build Coastguard Worker pDocument, pRecordNode, eDataNodeType,
1179*3ac0a46fSAndroid Build Coastguard Worker WideString(
1180*3ac0a46fSAndroid Build Coastguard Worker pFormNode->JSObject()->GetCData(XFA_Attribute::Name)));
1181*3ac0a46fSAndroid Build Coastguard Worker if (pDataNode) {
1182*3ac0a46fSAndroid Build Coastguard Worker CreateDataBinding(pFormNode, pDataNode, false);
1183*3ac0a46fSAndroid Build Coastguard Worker pDocument->RegisterGlobalBinding(pFormNode->GetNameHash(),
1184*3ac0a46fSAndroid Build Coastguard Worker pDataNode);
1185*3ac0a46fSAndroid Build Coastguard Worker }
1186*3ac0a46fSAndroid Build Coastguard Worker } else {
1187*3ac0a46fSAndroid Build Coastguard Worker CreateDataBinding(pFormNode, pDataNode, true);
1188*3ac0a46fSAndroid Build Coastguard Worker }
1189*3ac0a46fSAndroid Build Coastguard Worker }
1190*3ac0a46fSAndroid Build Coastguard Worker if (!pDataNode)
1191*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_MatchNoneCreateChild(pFormNode);
1192*3ac0a46fSAndroid Build Coastguard Worker }
1193*3ac0a46fSAndroid Build Coastguard Worker break;
1194*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::DataRef: {
1195*3ac0a46fSAndroid Build Coastguard Worker bMatchRef = bDataRef;
1196*3ac0a46fSAndroid Build Coastguard Worker bParentDataRef = true;
1197*3ac0a46fSAndroid Build Coastguard Worker if (!pDataNode && bDataRef) {
1198*3ac0a46fSAndroid Build Coastguard Worker WideString wsRef =
1199*3ac0a46fSAndroid Build Coastguard Worker pTemplateNodeBind
1200*3ac0a46fSAndroid Build Coastguard Worker ? pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref)
1201*3ac0a46fSAndroid Build Coastguard Worker : WideString();
1202*3ac0a46fSAndroid Build Coastguard Worker const Mask<XFA_ResolveFlag> kFlags = {XFA_ResolveFlag::kChildren,
1203*3ac0a46fSAndroid Build Coastguard Worker XFA_ResolveFlag::kCreateNode};
1204*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
1205*3ac0a46fSAndroid Build Coastguard Worker pDocument->GetScriptContext()->ResolveObjectsWithBindNode(
1206*3ac0a46fSAndroid Build Coastguard Worker pDataScope, wsRef.AsStringView(), kFlags, pTemplateNode);
1207*3ac0a46fSAndroid Build Coastguard Worker CXFA_Object* pObject =
1208*3ac0a46fSAndroid Build Coastguard Worker maybeResult.has_value() && !maybeResult.value().objects.empty()
1209*3ac0a46fSAndroid Build Coastguard Worker ? maybeResult.value().objects.front().Get()
1210*3ac0a46fSAndroid Build Coastguard Worker : nullptr;
1211*3ac0a46fSAndroid Build Coastguard Worker pDataNode = ToNode(pObject);
1212*3ac0a46fSAndroid Build Coastguard Worker if (pDataNode) {
1213*3ac0a46fSAndroid Build Coastguard Worker CreateDataBinding(
1214*3ac0a46fSAndroid Build Coastguard Worker pFormNode, pDataNode,
1215*3ac0a46fSAndroid Build Coastguard Worker maybeResult.value().type ==
1216*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::ResolveResult::Type::kExistNodes);
1217*3ac0a46fSAndroid Build Coastguard Worker } else {
1218*3ac0a46fSAndroid Build Coastguard Worker FormValueNode_MatchNoneCreateChild(pFormNode);
1219*3ac0a46fSAndroid Build Coastguard Worker }
1220*3ac0a46fSAndroid Build Coastguard Worker }
1221*3ac0a46fSAndroid Build Coastguard Worker break;
1222*3ac0a46fSAndroid Build Coastguard Worker }
1223*3ac0a46fSAndroid Build Coastguard Worker default:
1224*3ac0a46fSAndroid Build Coastguard Worker break;
1225*3ac0a46fSAndroid Build Coastguard Worker }
1226*3ac0a46fSAndroid Build Coastguard Worker }
1227*3ac0a46fSAndroid Build Coastguard Worker
1228*3ac0a46fSAndroid Build Coastguard Worker if (bMatchRef &&
1229*3ac0a46fSAndroid Build Coastguard Worker (eType == XFA_Element::Subform || eType == XFA_Element::SubformSet ||
1230*3ac0a46fSAndroid Build Coastguard Worker eType == XFA_Element::Area || eType == XFA_Element::PageArea ||
1231*3ac0a46fSAndroid Build Coastguard Worker eType == XFA_Element::PageSet)) {
1232*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pFormChild = pFormNode->GetFirstChild(); pFormChild;
1233*3ac0a46fSAndroid Build Coastguard Worker pFormChild = pFormChild->GetNextSibling()) {
1234*3ac0a46fSAndroid Build Coastguard Worker if (!pFormChild->IsContainerNode())
1235*3ac0a46fSAndroid Build Coastguard Worker continue;
1236*3ac0a46fSAndroid Build Coastguard Worker if (pFormChild->IsUnusedNode())
1237*3ac0a46fSAndroid Build Coastguard Worker continue;
1238*3ac0a46fSAndroid Build Coastguard Worker
1239*3ac0a46fSAndroid Build Coastguard Worker UpdateBindingRelations(pDocument, pFormChild,
1240*3ac0a46fSAndroid Build Coastguard Worker pDataNode ? pDataNode : pDataScope, bDataRef,
1241*3ac0a46fSAndroid Build Coastguard Worker bParentDataRef);
1242*3ac0a46fSAndroid Build Coastguard Worker }
1243*3ac0a46fSAndroid Build Coastguard Worker }
1244*3ac0a46fSAndroid Build Coastguard Worker }
1245*3ac0a46fSAndroid Build Coastguard Worker
UpdateDataRelation(CXFA_Node * pDataNode,CXFA_Node * pDataDescriptionNode)1246*3ac0a46fSAndroid Build Coastguard Worker void UpdateDataRelation(CXFA_Node* pDataNode, CXFA_Node* pDataDescriptionNode) {
1247*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pDataDescriptionNode);
1248*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pDataChild = pDataNode->GetFirstChild(); pDataChild;
1249*3ac0a46fSAndroid Build Coastguard Worker pDataChild = pDataChild->GetNextSibling()) {
1250*3ac0a46fSAndroid Build Coastguard Worker uint32_t dwNameHash = pDataChild->GetNameHash();
1251*3ac0a46fSAndroid Build Coastguard Worker if (!dwNameHash)
1252*3ac0a46fSAndroid Build Coastguard Worker continue;
1253*3ac0a46fSAndroid Build Coastguard Worker
1254*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup>
1255*3ac0a46fSAndroid Build Coastguard Worker sIterator(pDataDescriptionNode);
1256*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
1257*3ac0a46fSAndroid Build Coastguard Worker pDDGroupNode = sIterator.MoveToNext()) {
1258*3ac0a46fSAndroid Build Coastguard Worker if (pDDGroupNode != pDataDescriptionNode) {
1259*3ac0a46fSAndroid Build Coastguard Worker if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup)
1260*3ac0a46fSAndroid Build Coastguard Worker continue;
1261*3ac0a46fSAndroid Build Coastguard Worker
1262*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> ns =
1263*3ac0a46fSAndroid Build Coastguard Worker pDDGroupNode->JSObject()->TryNamespace();
1264*3ac0a46fSAndroid Build Coastguard Worker if (!ns.has_value() ||
1265*3ac0a46fSAndroid Build Coastguard Worker !ns.value().EqualsASCII("http://ns.adobe.com/data-description/")) {
1266*3ac0a46fSAndroid Build Coastguard Worker continue;
1267*3ac0a46fSAndroid Build Coastguard Worker }
1268*3ac0a46fSAndroid Build Coastguard Worker }
1269*3ac0a46fSAndroid Build Coastguard Worker
1270*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDDNode = pDDGroupNode->GetFirstChildByName(dwNameHash);
1271*3ac0a46fSAndroid Build Coastguard Worker if (!pDDNode)
1272*3ac0a46fSAndroid Build Coastguard Worker continue;
1273*3ac0a46fSAndroid Build Coastguard Worker if (pDDNode->GetElementType() != pDataChild->GetElementType())
1274*3ac0a46fSAndroid Build Coastguard Worker break;
1275*3ac0a46fSAndroid Build Coastguard Worker
1276*3ac0a46fSAndroid Build Coastguard Worker pDataChild->SetDataDescriptionNode(pDDNode);
1277*3ac0a46fSAndroid Build Coastguard Worker UpdateDataRelation(pDataChild, pDDNode);
1278*3ac0a46fSAndroid Build Coastguard Worker break;
1279*3ac0a46fSAndroid Build Coastguard Worker }
1280*3ac0a46fSAndroid Build Coastguard Worker }
1281*3ac0a46fSAndroid Build Coastguard Worker }
1282*3ac0a46fSAndroid Build Coastguard Worker
1283*3ac0a46fSAndroid Build Coastguard Worker } // namespace
1284*3ac0a46fSAndroid Build Coastguard Worker
CXFA_Document(CXFA_FFNotify * notify,cppgc::Heap * heap,LayoutProcessorIface * pLayout)1285*3ac0a46fSAndroid Build Coastguard Worker CXFA_Document::CXFA_Document(CXFA_FFNotify* notify,
1286*3ac0a46fSAndroid Build Coastguard Worker cppgc::Heap* heap,
1287*3ac0a46fSAndroid Build Coastguard Worker LayoutProcessorIface* pLayout)
1288*3ac0a46fSAndroid Build Coastguard Worker : heap_(heap),
1289*3ac0a46fSAndroid Build Coastguard Worker notify_(notify),
1290*3ac0a46fSAndroid Build Coastguard Worker node_owner_(cppgc::MakeGarbageCollected<CXFA_NodeOwner>(
1291*3ac0a46fSAndroid Build Coastguard Worker heap->GetAllocationHandle())),
1292*3ac0a46fSAndroid Build Coastguard Worker m_pLayoutProcessor(std::move(pLayout)) {
1293*3ac0a46fSAndroid Build Coastguard Worker if (m_pLayoutProcessor)
1294*3ac0a46fSAndroid Build Coastguard Worker m_pLayoutProcessor->SetDocument(this);
1295*3ac0a46fSAndroid Build Coastguard Worker }
1296*3ac0a46fSAndroid Build Coastguard Worker
1297*3ac0a46fSAndroid Build Coastguard Worker CXFA_Document::~CXFA_Document() = default;
1298*3ac0a46fSAndroid Build Coastguard Worker
Trace(cppgc::Visitor * visitor) const1299*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::Trace(cppgc::Visitor* visitor) const {
1300*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(notify_);
1301*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(node_owner_);
1302*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pRootNode);
1303*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pLocaleMgr);
1304*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pLayoutProcessor);
1305*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pScriptDataWindow);
1306*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pScriptEvent);
1307*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pScriptHost);
1308*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pScriptLog);
1309*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pScriptLayout);
1310*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pScriptSignature);
1311*3ac0a46fSAndroid Build Coastguard Worker ContainerTrace(visitor, m_rgGlobalBinding);
1312*3ac0a46fSAndroid Build Coastguard Worker ContainerTrace(visitor, m_pPendingPageSet);
1313*3ac0a46fSAndroid Build Coastguard Worker }
1314*3ac0a46fSAndroid Build Coastguard Worker
ClearLayoutData()1315*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::ClearLayoutData() {
1316*3ac0a46fSAndroid Build Coastguard Worker m_pLayoutProcessor = nullptr;
1317*3ac0a46fSAndroid Build Coastguard Worker m_pScriptContext.reset();
1318*3ac0a46fSAndroid Build Coastguard Worker m_pLocaleMgr.Clear();
1319*3ac0a46fSAndroid Build Coastguard Worker m_pScriptDataWindow = nullptr;
1320*3ac0a46fSAndroid Build Coastguard Worker m_pScriptEvent = nullptr;
1321*3ac0a46fSAndroid Build Coastguard Worker m_pScriptHost = nullptr;
1322*3ac0a46fSAndroid Build Coastguard Worker m_pScriptLog = nullptr;
1323*3ac0a46fSAndroid Build Coastguard Worker m_pScriptLayout = nullptr;
1324*3ac0a46fSAndroid Build Coastguard Worker m_pScriptSignature = nullptr;
1325*3ac0a46fSAndroid Build Coastguard Worker }
1326*3ac0a46fSAndroid Build Coastguard Worker
GetXFAObject(XFA_HashCode dwNodeNameHash)1327*3ac0a46fSAndroid Build Coastguard Worker CXFA_Object* CXFA_Document::GetXFAObject(XFA_HashCode dwNodeNameHash) {
1328*3ac0a46fSAndroid Build Coastguard Worker switch (dwNodeNameHash) {
1329*3ac0a46fSAndroid Build Coastguard Worker case XFA_HASHCODE_Data: {
1330*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDatasetsNode = ToNode(GetXFAObject(XFA_HASHCODE_Datasets));
1331*3ac0a46fSAndroid Build Coastguard Worker if (!pDatasetsNode)
1332*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
1333*3ac0a46fSAndroid Build Coastguard Worker
1334*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_DataGroup* pDatasetsChild =
1335*3ac0a46fSAndroid Build Coastguard Worker pDatasetsNode->GetFirstChildByClass<CXFA_DataGroup>(
1336*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::DataGroup);
1337*3ac0a46fSAndroid Build Coastguard Worker pDatasetsChild;
1338*3ac0a46fSAndroid Build Coastguard Worker pDatasetsChild =
1339*3ac0a46fSAndroid Build Coastguard Worker pDatasetsChild->GetNextSameClassSibling<CXFA_DataGroup>(
1340*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::DataGroup)) {
1341*3ac0a46fSAndroid Build Coastguard Worker if (pDatasetsChild->GetNameHash() != XFA_HASHCODE_Data)
1342*3ac0a46fSAndroid Build Coastguard Worker continue;
1343*3ac0a46fSAndroid Build Coastguard Worker
1344*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> namespaceURI =
1345*3ac0a46fSAndroid Build Coastguard Worker pDatasetsChild->JSObject()->TryNamespace();
1346*3ac0a46fSAndroid Build Coastguard Worker if (!namespaceURI.has_value())
1347*3ac0a46fSAndroid Build Coastguard Worker continue;
1348*3ac0a46fSAndroid Build Coastguard Worker
1349*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> datasetsURI =
1350*3ac0a46fSAndroid Build Coastguard Worker pDatasetsNode->JSObject()->TryNamespace();
1351*3ac0a46fSAndroid Build Coastguard Worker if (!datasetsURI.has_value())
1352*3ac0a46fSAndroid Build Coastguard Worker continue;
1353*3ac0a46fSAndroid Build Coastguard Worker if (namespaceURI.value() == datasetsURI.value())
1354*3ac0a46fSAndroid Build Coastguard Worker return pDatasetsChild;
1355*3ac0a46fSAndroid Build Coastguard Worker }
1356*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
1357*3ac0a46fSAndroid Build Coastguard Worker }
1358*3ac0a46fSAndroid Build Coastguard Worker case XFA_HASHCODE_Record: {
1359*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pData = ToNode(GetXFAObject(XFA_HASHCODE_Data));
1360*3ac0a46fSAndroid Build Coastguard Worker return pData ? pData->GetFirstChildByClass<CXFA_DataGroup>(
1361*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::DataGroup)
1362*3ac0a46fSAndroid Build Coastguard Worker : nullptr;
1363*3ac0a46fSAndroid Build Coastguard Worker }
1364*3ac0a46fSAndroid Build Coastguard Worker case XFA_HASHCODE_DataWindow: {
1365*3ac0a46fSAndroid Build Coastguard Worker if (!m_pScriptDataWindow)
1366*3ac0a46fSAndroid Build Coastguard Worker m_pScriptDataWindow = cppgc::MakeGarbageCollected<CScript_DataWindow>(
1367*3ac0a46fSAndroid Build Coastguard Worker GetHeap()->GetAllocationHandle(), this);
1368*3ac0a46fSAndroid Build Coastguard Worker return m_pScriptDataWindow;
1369*3ac0a46fSAndroid Build Coastguard Worker }
1370*3ac0a46fSAndroid Build Coastguard Worker case XFA_HASHCODE_Event: {
1371*3ac0a46fSAndroid Build Coastguard Worker if (!m_pScriptEvent)
1372*3ac0a46fSAndroid Build Coastguard Worker m_pScriptEvent = cppgc::MakeGarbageCollected<CScript_EventPseudoModel>(
1373*3ac0a46fSAndroid Build Coastguard Worker GetHeap()->GetAllocationHandle(), this);
1374*3ac0a46fSAndroid Build Coastguard Worker return m_pScriptEvent;
1375*3ac0a46fSAndroid Build Coastguard Worker }
1376*3ac0a46fSAndroid Build Coastguard Worker case XFA_HASHCODE_Host: {
1377*3ac0a46fSAndroid Build Coastguard Worker if (!m_pScriptHost)
1378*3ac0a46fSAndroid Build Coastguard Worker m_pScriptHost = cppgc::MakeGarbageCollected<CScript_HostPseudoModel>(
1379*3ac0a46fSAndroid Build Coastguard Worker GetHeap()->GetAllocationHandle(), this);
1380*3ac0a46fSAndroid Build Coastguard Worker return m_pScriptHost;
1381*3ac0a46fSAndroid Build Coastguard Worker }
1382*3ac0a46fSAndroid Build Coastguard Worker case XFA_HASHCODE_Log: {
1383*3ac0a46fSAndroid Build Coastguard Worker if (!m_pScriptLog)
1384*3ac0a46fSAndroid Build Coastguard Worker m_pScriptLog = cppgc::MakeGarbageCollected<CScript_LogPseudoModel>(
1385*3ac0a46fSAndroid Build Coastguard Worker GetHeap()->GetAllocationHandle(), this);
1386*3ac0a46fSAndroid Build Coastguard Worker return m_pScriptLog;
1387*3ac0a46fSAndroid Build Coastguard Worker }
1388*3ac0a46fSAndroid Build Coastguard Worker case XFA_HASHCODE_Signature: {
1389*3ac0a46fSAndroid Build Coastguard Worker if (!m_pScriptSignature)
1390*3ac0a46fSAndroid Build Coastguard Worker m_pScriptSignature =
1391*3ac0a46fSAndroid Build Coastguard Worker cppgc::MakeGarbageCollected<CScript_SignaturePseudoModel>(
1392*3ac0a46fSAndroid Build Coastguard Worker GetHeap()->GetAllocationHandle(), this);
1393*3ac0a46fSAndroid Build Coastguard Worker return m_pScriptSignature;
1394*3ac0a46fSAndroid Build Coastguard Worker }
1395*3ac0a46fSAndroid Build Coastguard Worker case XFA_HASHCODE_Layout: {
1396*3ac0a46fSAndroid Build Coastguard Worker if (!m_pScriptLayout)
1397*3ac0a46fSAndroid Build Coastguard Worker m_pScriptLayout =
1398*3ac0a46fSAndroid Build Coastguard Worker cppgc::MakeGarbageCollected<CScript_LayoutPseudoModel>(
1399*3ac0a46fSAndroid Build Coastguard Worker GetHeap()->GetAllocationHandle(), this);
1400*3ac0a46fSAndroid Build Coastguard Worker return m_pScriptLayout;
1401*3ac0a46fSAndroid Build Coastguard Worker }
1402*3ac0a46fSAndroid Build Coastguard Worker default:
1403*3ac0a46fSAndroid Build Coastguard Worker return m_pRootNode->GetFirstChildByName(dwNodeNameHash);
1404*3ac0a46fSAndroid Build Coastguard Worker }
1405*3ac0a46fSAndroid Build Coastguard Worker }
1406*3ac0a46fSAndroid Build Coastguard Worker
CreateNode(XFA_PacketType packet,XFA_Element eElement)1407*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CXFA_Document::CreateNode(XFA_PacketType packet,
1408*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eElement) {
1409*3ac0a46fSAndroid Build Coastguard Worker if (eElement == XFA_Element::Unknown)
1410*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
1411*3ac0a46fSAndroid Build Coastguard Worker
1412*3ac0a46fSAndroid Build Coastguard Worker return CXFA_Node::Create(this, eElement, packet);
1413*3ac0a46fSAndroid Build Coastguard Worker }
1414*3ac0a46fSAndroid Build Coastguard Worker
IsInteractive()1415*3ac0a46fSAndroid Build Coastguard Worker bool CXFA_Document::IsInteractive() {
1416*3ac0a46fSAndroid Build Coastguard Worker if (m_Interactive.has_value())
1417*3ac0a46fSAndroid Build Coastguard Worker return m_Interactive.value();
1418*3ac0a46fSAndroid Build Coastguard Worker
1419*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pConfig = ToNode(GetXFAObject(XFA_HASHCODE_Config));
1420*3ac0a46fSAndroid Build Coastguard Worker if (!pConfig)
1421*3ac0a46fSAndroid Build Coastguard Worker return false;
1422*3ac0a46fSAndroid Build Coastguard Worker
1423*3ac0a46fSAndroid Build Coastguard Worker CXFA_Present* pPresent =
1424*3ac0a46fSAndroid Build Coastguard Worker pConfig->GetFirstChildByClass<CXFA_Present>(XFA_Element::Present);
1425*3ac0a46fSAndroid Build Coastguard Worker if (!pPresent)
1426*3ac0a46fSAndroid Build Coastguard Worker return false;
1427*3ac0a46fSAndroid Build Coastguard Worker
1428*3ac0a46fSAndroid Build Coastguard Worker CXFA_Pdf* pPDF = pPresent->GetFirstChildByClass<CXFA_Pdf>(XFA_Element::Pdf);
1429*3ac0a46fSAndroid Build Coastguard Worker if (!pPDF)
1430*3ac0a46fSAndroid Build Coastguard Worker return false;
1431*3ac0a46fSAndroid Build Coastguard Worker
1432*3ac0a46fSAndroid Build Coastguard Worker CXFA_Interactive* pFormFiller =
1433*3ac0a46fSAndroid Build Coastguard Worker pPDF->GetChild<CXFA_Interactive>(0, XFA_Element::Interactive, false);
1434*3ac0a46fSAndroid Build Coastguard Worker if (!pFormFiller)
1435*3ac0a46fSAndroid Build Coastguard Worker return false;
1436*3ac0a46fSAndroid Build Coastguard Worker
1437*3ac0a46fSAndroid Build Coastguard Worker WideString wsInteractive = pFormFiller->JSObject()->GetContent(false);
1438*3ac0a46fSAndroid Build Coastguard Worker bool bInteractive = wsInteractive.EqualsASCII("1");
1439*3ac0a46fSAndroid Build Coastguard Worker m_Interactive = bInteractive;
1440*3ac0a46fSAndroid Build Coastguard Worker return bInteractive;
1441*3ac0a46fSAndroid Build Coastguard Worker }
1442*3ac0a46fSAndroid Build Coastguard Worker
GetLocaleMgr()1443*3ac0a46fSAndroid Build Coastguard Worker CXFA_LocaleMgr* CXFA_Document::GetLocaleMgr() {
1444*3ac0a46fSAndroid Build Coastguard Worker if (!m_pLocaleMgr) {
1445*3ac0a46fSAndroid Build Coastguard Worker m_pLocaleMgr = cppgc::MakeGarbageCollected<CXFA_LocaleMgr>(
1446*3ac0a46fSAndroid Build Coastguard Worker heap_->GetAllocationHandle(), heap_,
1447*3ac0a46fSAndroid Build Coastguard Worker ToNode(GetXFAObject(XFA_HASHCODE_LocaleSet)),
1448*3ac0a46fSAndroid Build Coastguard Worker GetNotify()->GetAppProvider()->GetLanguage());
1449*3ac0a46fSAndroid Build Coastguard Worker }
1450*3ac0a46fSAndroid Build Coastguard Worker return m_pLocaleMgr;
1451*3ac0a46fSAndroid Build Coastguard Worker }
1452*3ac0a46fSAndroid Build Coastguard Worker
GetHeap() const1453*3ac0a46fSAndroid Build Coastguard Worker cppgc::Heap* CXFA_Document::GetHeap() const {
1454*3ac0a46fSAndroid Build Coastguard Worker return heap_;
1455*3ac0a46fSAndroid Build Coastguard Worker }
1456*3ac0a46fSAndroid Build Coastguard Worker
InitScriptContext(CJS_Runtime * fxjs_runtime)1457*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine* CXFA_Document::InitScriptContext(CJS_Runtime* fxjs_runtime) {
1458*3ac0a46fSAndroid Build Coastguard Worker DCHECK(!m_pScriptContext);
1459*3ac0a46fSAndroid Build Coastguard Worker m_pScriptContext = std::make_unique<CFXJSE_Engine>(this, fxjs_runtime);
1460*3ac0a46fSAndroid Build Coastguard Worker return m_pScriptContext.get();
1461*3ac0a46fSAndroid Build Coastguard Worker }
1462*3ac0a46fSAndroid Build Coastguard Worker
GetScriptContext() const1463*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine* CXFA_Document::GetScriptContext() const {
1464*3ac0a46fSAndroid Build Coastguard Worker DCHECK(m_pScriptContext);
1465*3ac0a46fSAndroid Build Coastguard Worker return m_pScriptContext.get();
1466*3ac0a46fSAndroid Build Coastguard Worker }
1467*3ac0a46fSAndroid Build Coastguard Worker
RecognizeXFAVersionNumber(const WideString & wsTemplateNS)1468*3ac0a46fSAndroid Build Coastguard Worker XFA_VERSION CXFA_Document::RecognizeXFAVersionNumber(
1469*3ac0a46fSAndroid Build Coastguard Worker const WideString& wsTemplateNS) {
1470*3ac0a46fSAndroid Build Coastguard Worker XFA_VERSION eVersion = ParseXFAVersion(wsTemplateNS);
1471*3ac0a46fSAndroid Build Coastguard Worker if (eVersion != XFA_VERSION_UNKNOWN)
1472*3ac0a46fSAndroid Build Coastguard Worker m_eCurVersionMode = eVersion;
1473*3ac0a46fSAndroid Build Coastguard Worker
1474*3ac0a46fSAndroid Build Coastguard Worker return eVersion;
1475*3ac0a46fSAndroid Build Coastguard Worker }
1476*3ac0a46fSAndroid Build Coastguard Worker
1477*3ac0a46fSAndroid Build Coastguard Worker // static
ParseXFAVersion(const WideString & wsTemplateNS)1478*3ac0a46fSAndroid Build Coastguard Worker XFA_VERSION CXFA_Document::ParseXFAVersion(const WideString& wsTemplateNS) {
1479*3ac0a46fSAndroid Build Coastguard Worker WideStringView wsTemplateURIPrefix(kTemplateNS);
1480*3ac0a46fSAndroid Build Coastguard Worker if (wsTemplateNS.GetLength() <= wsTemplateURIPrefix.GetLength())
1481*3ac0a46fSAndroid Build Coastguard Worker return XFA_VERSION_UNKNOWN;
1482*3ac0a46fSAndroid Build Coastguard Worker
1483*3ac0a46fSAndroid Build Coastguard Worker size_t prefixLength = wsTemplateURIPrefix.GetLength();
1484*3ac0a46fSAndroid Build Coastguard Worker if (wsTemplateNS.AsStringView().First(prefixLength) != wsTemplateURIPrefix)
1485*3ac0a46fSAndroid Build Coastguard Worker return XFA_VERSION_UNKNOWN;
1486*3ac0a46fSAndroid Build Coastguard Worker
1487*3ac0a46fSAndroid Build Coastguard Worker auto nDotPos = wsTemplateNS.Find('.', prefixLength);
1488*3ac0a46fSAndroid Build Coastguard Worker if (!nDotPos.has_value())
1489*3ac0a46fSAndroid Build Coastguard Worker return XFA_VERSION_UNKNOWN;
1490*3ac0a46fSAndroid Build Coastguard Worker
1491*3ac0a46fSAndroid Build Coastguard Worker int8_t iMajor = FXSYS_wtoi(
1492*3ac0a46fSAndroid Build Coastguard Worker wsTemplateNS.Substr(prefixLength, nDotPos.value() - prefixLength)
1493*3ac0a46fSAndroid Build Coastguard Worker .c_str());
1494*3ac0a46fSAndroid Build Coastguard Worker int8_t iMinor = FXSYS_wtoi(wsTemplateNS.Substr(nDotPos.value() + 1).c_str());
1495*3ac0a46fSAndroid Build Coastguard Worker XFA_VERSION eVersion =
1496*3ac0a46fSAndroid Build Coastguard Worker static_cast<XFA_VERSION>(static_cast<int32_t>(iMajor) * 100 + iMinor);
1497*3ac0a46fSAndroid Build Coastguard Worker if (eVersion < XFA_VERSION_MIN || eVersion > XFA_VERSION_MAX)
1498*3ac0a46fSAndroid Build Coastguard Worker return XFA_VERSION_UNKNOWN;
1499*3ac0a46fSAndroid Build Coastguard Worker
1500*3ac0a46fSAndroid Build Coastguard Worker return eVersion;
1501*3ac0a46fSAndroid Build Coastguard Worker }
1502*3ac0a46fSAndroid Build Coastguard Worker
GetFormType() const1503*3ac0a46fSAndroid Build Coastguard Worker FormType CXFA_Document::GetFormType() const {
1504*3ac0a46fSAndroid Build Coastguard Worker return GetNotify()->GetFFDoc()->GetFormType();
1505*3ac0a46fSAndroid Build Coastguard Worker }
1506*3ac0a46fSAndroid Build Coastguard Worker
GetNodeByID(CXFA_Node * pRoot,WideStringView wsID) const1507*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CXFA_Document::GetNodeByID(CXFA_Node* pRoot,
1508*3ac0a46fSAndroid Build Coastguard Worker WideStringView wsID) const {
1509*3ac0a46fSAndroid Build Coastguard Worker if (!pRoot || wsID.IsEmpty())
1510*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
1511*3ac0a46fSAndroid Build Coastguard Worker
1512*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIterator sIterator(pRoot);
1513*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
1514*3ac0a46fSAndroid Build Coastguard Worker pNode = sIterator.MoveToNext()) {
1515*3ac0a46fSAndroid Build Coastguard Worker WideString wsIDVal = pNode->JSObject()->GetCData(XFA_Attribute::Id);
1516*3ac0a46fSAndroid Build Coastguard Worker if (!wsIDVal.IsEmpty() && wsIDVal == wsID)
1517*3ac0a46fSAndroid Build Coastguard Worker return pNode;
1518*3ac0a46fSAndroid Build Coastguard Worker }
1519*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
1520*3ac0a46fSAndroid Build Coastguard Worker }
1521*3ac0a46fSAndroid Build Coastguard Worker
DoProtoMerge()1522*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::DoProtoMerge() {
1523*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pTemplateRoot = ToNode(GetXFAObject(XFA_HASHCODE_Template));
1524*3ac0a46fSAndroid Build Coastguard Worker if (!pTemplateRoot)
1525*3ac0a46fSAndroid Build Coastguard Worker return;
1526*3ac0a46fSAndroid Build Coastguard Worker
1527*3ac0a46fSAndroid Build Coastguard Worker std::map<uint32_t, CXFA_Node*> mIDMap;
1528*3ac0a46fSAndroid Build Coastguard Worker std::set<CXFA_Node*> sUseNodes;
1529*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIterator sIterator(pTemplateRoot);
1530*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
1531*3ac0a46fSAndroid Build Coastguard Worker pNode = sIterator.MoveToNext()) {
1532*3ac0a46fSAndroid Build Coastguard Worker WideString wsIDVal = pNode->JSObject()->GetCData(XFA_Attribute::Id);
1533*3ac0a46fSAndroid Build Coastguard Worker if (!wsIDVal.IsEmpty())
1534*3ac0a46fSAndroid Build Coastguard Worker mIDMap[FX_HashCode_GetW(wsIDVal.AsStringView())] = pNode;
1535*3ac0a46fSAndroid Build Coastguard Worker
1536*3ac0a46fSAndroid Build Coastguard Worker WideString wsUseVal = pNode->JSObject()->GetCData(XFA_Attribute::Use);
1537*3ac0a46fSAndroid Build Coastguard Worker if (!wsUseVal.IsEmpty()) {
1538*3ac0a46fSAndroid Build Coastguard Worker sUseNodes.insert(pNode);
1539*3ac0a46fSAndroid Build Coastguard Worker } else {
1540*3ac0a46fSAndroid Build Coastguard Worker wsUseVal = pNode->JSObject()->GetCData(XFA_Attribute::Usehref);
1541*3ac0a46fSAndroid Build Coastguard Worker if (!wsUseVal.IsEmpty())
1542*3ac0a46fSAndroid Build Coastguard Worker sUseNodes.insert(pNode);
1543*3ac0a46fSAndroid Build Coastguard Worker }
1544*3ac0a46fSAndroid Build Coastguard Worker }
1545*3ac0a46fSAndroid Build Coastguard Worker
1546*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pUseHrefNode : sUseNodes) {
1547*3ac0a46fSAndroid Build Coastguard Worker // Must outlive the WideStringViews below.
1548*3ac0a46fSAndroid Build Coastguard Worker WideString wsUseVal =
1549*3ac0a46fSAndroid Build Coastguard Worker pUseHrefNode->JSObject()->GetCData(XFA_Attribute::Usehref);
1550*3ac0a46fSAndroid Build Coastguard Worker WideStringView wsURI;
1551*3ac0a46fSAndroid Build Coastguard Worker WideStringView wsID;
1552*3ac0a46fSAndroid Build Coastguard Worker WideStringView wsSOM;
1553*3ac0a46fSAndroid Build Coastguard Worker if (!wsUseVal.IsEmpty()) {
1554*3ac0a46fSAndroid Build Coastguard Worker ParseUseHref(wsUseVal, wsURI, wsID, wsSOM);
1555*3ac0a46fSAndroid Build Coastguard Worker if (!wsURI.IsEmpty() && !wsURI.EqualsASCII("."))
1556*3ac0a46fSAndroid Build Coastguard Worker continue;
1557*3ac0a46fSAndroid Build Coastguard Worker } else {
1558*3ac0a46fSAndroid Build Coastguard Worker wsUseVal = pUseHrefNode->JSObject()->GetCData(XFA_Attribute::Use);
1559*3ac0a46fSAndroid Build Coastguard Worker ParseUse(wsUseVal, wsID, wsSOM);
1560*3ac0a46fSAndroid Build Coastguard Worker }
1561*3ac0a46fSAndroid Build Coastguard Worker
1562*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pProtoNode = nullptr;
1563*3ac0a46fSAndroid Build Coastguard Worker if (!wsSOM.IsEmpty()) {
1564*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
1565*3ac0a46fSAndroid Build Coastguard Worker m_pScriptContext->ResolveObjects(
1566*3ac0a46fSAndroid Build Coastguard Worker pUseHrefNode, wsSOM,
1567*3ac0a46fSAndroid Build Coastguard Worker Mask<XFA_ResolveFlag>{
1568*3ac0a46fSAndroid Build Coastguard Worker XFA_ResolveFlag::kChildren, XFA_ResolveFlag::kAttributes,
1569*3ac0a46fSAndroid Build Coastguard Worker XFA_ResolveFlag::kProperties, XFA_ResolveFlag::kParent,
1570*3ac0a46fSAndroid Build Coastguard Worker XFA_ResolveFlag::kSiblings});
1571*3ac0a46fSAndroid Build Coastguard Worker if (maybeResult.has_value()) {
1572*3ac0a46fSAndroid Build Coastguard Worker auto* pFirstObject = maybeResult.value().objects.front().Get();
1573*3ac0a46fSAndroid Build Coastguard Worker if (pFirstObject && pFirstObject->IsNode())
1574*3ac0a46fSAndroid Build Coastguard Worker pProtoNode = pFirstObject->AsNode();
1575*3ac0a46fSAndroid Build Coastguard Worker }
1576*3ac0a46fSAndroid Build Coastguard Worker } else if (!wsID.IsEmpty()) {
1577*3ac0a46fSAndroid Build Coastguard Worker auto it = mIDMap.find(FX_HashCode_GetW(wsID));
1578*3ac0a46fSAndroid Build Coastguard Worker if (it == mIDMap.end())
1579*3ac0a46fSAndroid Build Coastguard Worker continue;
1580*3ac0a46fSAndroid Build Coastguard Worker pProtoNode = it->second;
1581*3ac0a46fSAndroid Build Coastguard Worker }
1582*3ac0a46fSAndroid Build Coastguard Worker if (!pProtoNode)
1583*3ac0a46fSAndroid Build Coastguard Worker continue;
1584*3ac0a46fSAndroid Build Coastguard Worker
1585*3ac0a46fSAndroid Build Coastguard Worker MergeNode(pUseHrefNode, pProtoNode);
1586*3ac0a46fSAndroid Build Coastguard Worker }
1587*3ac0a46fSAndroid Build Coastguard Worker }
1588*3ac0a46fSAndroid Build Coastguard Worker
1589*3ac0a46fSAndroid Build Coastguard Worker // static
ParseUseHref(const WideString & wsUseVal,WideStringView & wsURI,WideStringView & wsID,WideStringView & wsSOM)1590*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::ParseUseHref(const WideString& wsUseVal,
1591*3ac0a46fSAndroid Build Coastguard Worker WideStringView& wsURI,
1592*3ac0a46fSAndroid Build Coastguard Worker WideStringView& wsID,
1593*3ac0a46fSAndroid Build Coastguard Worker WideStringView& wsSOM) {
1594*3ac0a46fSAndroid Build Coastguard Worker if (wsUseVal.IsEmpty())
1595*3ac0a46fSAndroid Build Coastguard Worker return;
1596*3ac0a46fSAndroid Build Coastguard Worker
1597*3ac0a46fSAndroid Build Coastguard Worker auto uSharpPos = wsUseVal.Find('#');
1598*3ac0a46fSAndroid Build Coastguard Worker if (!uSharpPos.has_value()) {
1599*3ac0a46fSAndroid Build Coastguard Worker wsURI = wsUseVal.AsStringView();
1600*3ac0a46fSAndroid Build Coastguard Worker return;
1601*3ac0a46fSAndroid Build Coastguard Worker }
1602*3ac0a46fSAndroid Build Coastguard Worker wsURI = wsUseVal.AsStringView().First(uSharpPos.value());
1603*3ac0a46fSAndroid Build Coastguard Worker if (wsUseVal.AsStringView().Substr(uSharpPos.value(), 5) == L"#som(" &&
1604*3ac0a46fSAndroid Build Coastguard Worker wsUseVal.Back() == ')') {
1605*3ac0a46fSAndroid Build Coastguard Worker wsSOM = wsUseVal.AsStringView().Substr(
1606*3ac0a46fSAndroid Build Coastguard Worker uSharpPos.value() + 5,
1607*3ac0a46fSAndroid Build Coastguard Worker wsUseVal.GetLength() - 1 - uSharpPos.value() - 5);
1608*3ac0a46fSAndroid Build Coastguard Worker return;
1609*3ac0a46fSAndroid Build Coastguard Worker }
1610*3ac0a46fSAndroid Build Coastguard Worker wsID = wsUseVal.AsStringView().Substr(uSharpPos.value() + 1);
1611*3ac0a46fSAndroid Build Coastguard Worker }
1612*3ac0a46fSAndroid Build Coastguard Worker
1613*3ac0a46fSAndroid Build Coastguard Worker // static
ParseUse(const WideString & wsUseVal,WideStringView & wsID,WideStringView & wsSOM)1614*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::ParseUse(const WideString& wsUseVal,
1615*3ac0a46fSAndroid Build Coastguard Worker WideStringView& wsID,
1616*3ac0a46fSAndroid Build Coastguard Worker WideStringView& wsSOM) {
1617*3ac0a46fSAndroid Build Coastguard Worker if (wsUseVal.IsEmpty())
1618*3ac0a46fSAndroid Build Coastguard Worker return;
1619*3ac0a46fSAndroid Build Coastguard Worker
1620*3ac0a46fSAndroid Build Coastguard Worker if (wsUseVal[0] == '#') {
1621*3ac0a46fSAndroid Build Coastguard Worker wsID = wsUseVal.AsStringView().Substr(1);
1622*3ac0a46fSAndroid Build Coastguard Worker return;
1623*3ac0a46fSAndroid Build Coastguard Worker }
1624*3ac0a46fSAndroid Build Coastguard Worker wsSOM = wsUseVal.AsStringView();
1625*3ac0a46fSAndroid Build Coastguard Worker }
1626*3ac0a46fSAndroid Build Coastguard Worker
DataMerge_CopyContainer(CXFA_Node * pTemplateNode,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bOneInstance,bool bDataMerge,bool bUpLevel)1627*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CXFA_Document::DataMerge_CopyContainer(CXFA_Node* pTemplateNode,
1628*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFormNode,
1629*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataScope,
1630*3ac0a46fSAndroid Build Coastguard Worker bool bOneInstance,
1631*3ac0a46fSAndroid Build Coastguard Worker bool bDataMerge,
1632*3ac0a46fSAndroid Build Coastguard Worker bool bUpLevel) {
1633*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pTemplateNode->IsContainerNode());
1634*3ac0a46fSAndroid Build Coastguard Worker switch (pTemplateNode->GetElementType()) {
1635*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::Area:
1636*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::PageArea:
1637*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::Subform:
1638*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::SubformSet:
1639*3ac0a46fSAndroid Build Coastguard Worker return CopyContainer_SubformSet(this, pTemplateNode, pFormNode,
1640*3ac0a46fSAndroid Build Coastguard Worker pDataScope, bOneInstance, bDataMerge);
1641*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::ContentArea:
1642*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::Draw:
1643*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::ExclGroup:
1644*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::Field:
1645*3ac0a46fSAndroid Build Coastguard Worker return CopyContainer_Field(this, pTemplateNode, pFormNode, pDataScope,
1646*3ac0a46fSAndroid Build Coastguard Worker bDataMerge, bUpLevel);
1647*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::PageSet:
1648*3ac0a46fSAndroid Build Coastguard Worker case XFA_Element::Variables:
1649*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
1650*3ac0a46fSAndroid Build Coastguard Worker default:
1651*3ac0a46fSAndroid Build Coastguard Worker NOTREACHED_NORETURN();
1652*3ac0a46fSAndroid Build Coastguard Worker }
1653*3ac0a46fSAndroid Build Coastguard Worker }
1654*3ac0a46fSAndroid Build Coastguard Worker
DataMerge_UpdateBindingRelations(CXFA_Node * pFormUpdateRoot)1655*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::DataMerge_UpdateBindingRelations(
1656*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFormUpdateRoot) {
1657*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataScope =
1658*3ac0a46fSAndroid Build Coastguard Worker XFA_DataMerge_FindDataScope(pFormUpdateRoot->GetParent());
1659*3ac0a46fSAndroid Build Coastguard Worker if (!pDataScope)
1660*3ac0a46fSAndroid Build Coastguard Worker return;
1661*3ac0a46fSAndroid Build Coastguard Worker
1662*3ac0a46fSAndroid Build Coastguard Worker UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, false, false);
1663*3ac0a46fSAndroid Build Coastguard Worker UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, true, false);
1664*3ac0a46fSAndroid Build Coastguard Worker }
1665*3ac0a46fSAndroid Build Coastguard Worker
GetNotBindNode(pdfium::span<cppgc::Member<CXFA_Object>> arrayObjects) const1666*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CXFA_Document::GetNotBindNode(
1667*3ac0a46fSAndroid Build Coastguard Worker pdfium::span<cppgc::Member<CXFA_Object>> arrayObjects) const {
1668*3ac0a46fSAndroid Build Coastguard Worker for (auto& pObject : arrayObjects) {
1669*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNode = pObject->AsNode();
1670*3ac0a46fSAndroid Build Coastguard Worker if (pNode && !pNode->HasBindItem())
1671*3ac0a46fSAndroid Build Coastguard Worker return pNode;
1672*3ac0a46fSAndroid Build Coastguard Worker }
1673*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
1674*3ac0a46fSAndroid Build Coastguard Worker }
1675*3ac0a46fSAndroid Build Coastguard Worker
DoDataMerge()1676*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::DoDataMerge() {
1677*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDatasetsRoot = ToNode(GetXFAObject(XFA_HASHCODE_Datasets));
1678*3ac0a46fSAndroid Build Coastguard Worker if (!pDatasetsRoot) {
1679*3ac0a46fSAndroid Build Coastguard Worker // Ownership will be passed in the AppendChild below to the XML tree.
1680*3ac0a46fSAndroid Build Coastguard Worker auto* pDatasetsXMLNode =
1681*3ac0a46fSAndroid Build Coastguard Worker notify_->GetFFDoc()->GetXMLDocument()->CreateNode<CFX_XMLElement>(
1682*3ac0a46fSAndroid Build Coastguard Worker L"xfa:datasets");
1683*3ac0a46fSAndroid Build Coastguard Worker pDatasetsXMLNode->SetAttribute(L"xmlns:xfa",
1684*3ac0a46fSAndroid Build Coastguard Worker L"http://www.xfa.org/schema/xfa-data/1.0/");
1685*3ac0a46fSAndroid Build Coastguard Worker pDatasetsRoot =
1686*3ac0a46fSAndroid Build Coastguard Worker CreateNode(XFA_PacketType::Datasets, XFA_Element::DataModel);
1687*3ac0a46fSAndroid Build Coastguard Worker pDatasetsRoot->JSObject()->SetCData(XFA_Attribute::Name, L"datasets");
1688*3ac0a46fSAndroid Build Coastguard Worker
1689*3ac0a46fSAndroid Build Coastguard Worker m_pRootNode->GetXMLMappingNode()->AppendLastChild(pDatasetsXMLNode);
1690*3ac0a46fSAndroid Build Coastguard Worker m_pRootNode->InsertChildAndNotify(pDatasetsRoot, nullptr);
1691*3ac0a46fSAndroid Build Coastguard Worker pDatasetsRoot->SetXMLMappingNode(pDatasetsXMLNode);
1692*3ac0a46fSAndroid Build Coastguard Worker }
1693*3ac0a46fSAndroid Build Coastguard Worker
1694*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataRoot = nullptr;
1695*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDDRoot = nullptr;
1696*3ac0a46fSAndroid Build Coastguard Worker WideString wsDatasetsURI =
1697*3ac0a46fSAndroid Build Coastguard Worker pDatasetsRoot->JSObject()->TryNamespace().value_or(WideString());
1698*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pChildNode = pDatasetsRoot->GetFirstChild(); pChildNode;
1699*3ac0a46fSAndroid Build Coastguard Worker pChildNode = pChildNode->GetNextSibling()) {
1700*3ac0a46fSAndroid Build Coastguard Worker if (pChildNode->GetElementType() != XFA_Element::DataGroup)
1701*3ac0a46fSAndroid Build Coastguard Worker continue;
1702*3ac0a46fSAndroid Build Coastguard Worker
1703*3ac0a46fSAndroid Build Coastguard Worker if (!pDDRoot && pChildNode->GetNameHash() == XFA_HASHCODE_DataDescription) {
1704*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> namespaceURI =
1705*3ac0a46fSAndroid Build Coastguard Worker pChildNode->JSObject()->TryNamespace();
1706*3ac0a46fSAndroid Build Coastguard Worker if (!namespaceURI.has_value())
1707*3ac0a46fSAndroid Build Coastguard Worker continue;
1708*3ac0a46fSAndroid Build Coastguard Worker if (namespaceURI.value().EqualsASCII(
1709*3ac0a46fSAndroid Build Coastguard Worker "http://ns.adobe.com/data-description/")) {
1710*3ac0a46fSAndroid Build Coastguard Worker pDDRoot = pChildNode;
1711*3ac0a46fSAndroid Build Coastguard Worker }
1712*3ac0a46fSAndroid Build Coastguard Worker } else if (!pDataRoot && pChildNode->GetNameHash() == XFA_HASHCODE_Data) {
1713*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> namespaceURI =
1714*3ac0a46fSAndroid Build Coastguard Worker pChildNode->JSObject()->TryNamespace();
1715*3ac0a46fSAndroid Build Coastguard Worker if (!namespaceURI.has_value())
1716*3ac0a46fSAndroid Build Coastguard Worker continue;
1717*3ac0a46fSAndroid Build Coastguard Worker if (namespaceURI == wsDatasetsURI)
1718*3ac0a46fSAndroid Build Coastguard Worker pDataRoot = pChildNode;
1719*3ac0a46fSAndroid Build Coastguard Worker }
1720*3ac0a46fSAndroid Build Coastguard Worker if (pDataRoot && pDDRoot)
1721*3ac0a46fSAndroid Build Coastguard Worker break;
1722*3ac0a46fSAndroid Build Coastguard Worker }
1723*3ac0a46fSAndroid Build Coastguard Worker
1724*3ac0a46fSAndroid Build Coastguard Worker if (!pDataRoot) {
1725*3ac0a46fSAndroid Build Coastguard Worker pDataRoot = CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup);
1726*3ac0a46fSAndroid Build Coastguard Worker pDataRoot->JSObject()->SetCData(XFA_Attribute::Name, L"data");
1727*3ac0a46fSAndroid Build Coastguard Worker
1728*3ac0a46fSAndroid Build Coastguard Worker auto* elem =
1729*3ac0a46fSAndroid Build Coastguard Worker notify_->GetFFDoc()->GetXMLDocument()->CreateNode<CFX_XMLElement>(
1730*3ac0a46fSAndroid Build Coastguard Worker L"xfa:data");
1731*3ac0a46fSAndroid Build Coastguard Worker pDataRoot->SetXMLMappingNode(elem);
1732*3ac0a46fSAndroid Build Coastguard Worker pDatasetsRoot->InsertChildAndNotify(pDataRoot, nullptr);
1733*3ac0a46fSAndroid Build Coastguard Worker }
1734*3ac0a46fSAndroid Build Coastguard Worker
1735*3ac0a46fSAndroid Build Coastguard Worker CXFA_DataGroup* pDataTopLevel =
1736*3ac0a46fSAndroid Build Coastguard Worker pDataRoot->GetFirstChildByClass<CXFA_DataGroup>(XFA_Element::DataGroup);
1737*3ac0a46fSAndroid Build Coastguard Worker uint32_t dwNameHash = pDataTopLevel ? pDataTopLevel->GetNameHash() : 0;
1738*3ac0a46fSAndroid Build Coastguard Worker CXFA_Template* pTemplateRoot =
1739*3ac0a46fSAndroid Build Coastguard Worker m_pRootNode->GetFirstChildByClass<CXFA_Template>(XFA_Element::Template);
1740*3ac0a46fSAndroid Build Coastguard Worker if (!pTemplateRoot)
1741*3ac0a46fSAndroid Build Coastguard Worker return;
1742*3ac0a46fSAndroid Build Coastguard Worker
1743*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pTemplateChosen =
1744*3ac0a46fSAndroid Build Coastguard Worker dwNameHash != 0 ? pTemplateRoot->GetFirstChildByName(dwNameHash)
1745*3ac0a46fSAndroid Build Coastguard Worker : nullptr;
1746*3ac0a46fSAndroid Build Coastguard Worker if (!pTemplateChosen ||
1747*3ac0a46fSAndroid Build Coastguard Worker pTemplateChosen->GetElementType() != XFA_Element::Subform) {
1748*3ac0a46fSAndroid Build Coastguard Worker pTemplateChosen =
1749*3ac0a46fSAndroid Build Coastguard Worker pTemplateRoot->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform);
1750*3ac0a46fSAndroid Build Coastguard Worker }
1751*3ac0a46fSAndroid Build Coastguard Worker if (!pTemplateChosen)
1752*3ac0a46fSAndroid Build Coastguard Worker return;
1753*3ac0a46fSAndroid Build Coastguard Worker
1754*3ac0a46fSAndroid Build Coastguard Worker CXFA_Form* pFormRoot =
1755*3ac0a46fSAndroid Build Coastguard Worker m_pRootNode->GetFirstChildByClass<CXFA_Form>(XFA_Element::Form);
1756*3ac0a46fSAndroid Build Coastguard Worker bool bEmptyForm = false;
1757*3ac0a46fSAndroid Build Coastguard Worker if (!pFormRoot) {
1758*3ac0a46fSAndroid Build Coastguard Worker bEmptyForm = true;
1759*3ac0a46fSAndroid Build Coastguard Worker pFormRoot = static_cast<CXFA_Form*>(
1760*3ac0a46fSAndroid Build Coastguard Worker CreateNode(XFA_PacketType::Form, XFA_Element::Form));
1761*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pFormRoot);
1762*3ac0a46fSAndroid Build Coastguard Worker pFormRoot->JSObject()->SetCData(XFA_Attribute::Name, L"form");
1763*3ac0a46fSAndroid Build Coastguard Worker m_pRootNode->InsertChildAndNotify(pFormRoot, nullptr);
1764*3ac0a46fSAndroid Build Coastguard Worker } else {
1765*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode>
1766*3ac0a46fSAndroid Build Coastguard Worker sIterator(pFormRoot);
1767*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pNode = sIterator.MoveToNext(); pNode;
1768*3ac0a46fSAndroid Build Coastguard Worker pNode = sIterator.MoveToNext()) {
1769*3ac0a46fSAndroid Build Coastguard Worker pNode->SetFlag(XFA_NodeFlag::kUnusedNode);
1770*3ac0a46fSAndroid Build Coastguard Worker }
1771*3ac0a46fSAndroid Build Coastguard Worker }
1772*3ac0a46fSAndroid Build Coastguard Worker
1773*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
1774*3ac0a46fSAndroid Build Coastguard Worker this, pFormRoot, pTemplateChosen, false, nullptr);
1775*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pSubformSetNode);
1776*3ac0a46fSAndroid Build Coastguard Worker if (!pDataTopLevel) {
1777*3ac0a46fSAndroid Build Coastguard Worker WideString wsFormName =
1778*3ac0a46fSAndroid Build Coastguard Worker pSubformSetNode->JSObject()->GetCData(XFA_Attribute::Name);
1779*3ac0a46fSAndroid Build Coastguard Worker WideString wsDataTopLevelName(wsFormName.IsEmpty() ? L"form" : wsFormName);
1780*3ac0a46fSAndroid Build Coastguard Worker
1781*3ac0a46fSAndroid Build Coastguard Worker pDataTopLevel = static_cast<CXFA_DataGroup*>(
1782*3ac0a46fSAndroid Build Coastguard Worker CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup));
1783*3ac0a46fSAndroid Build Coastguard Worker pDataTopLevel->JSObject()->SetCData(XFA_Attribute::Name,
1784*3ac0a46fSAndroid Build Coastguard Worker wsDataTopLevelName);
1785*3ac0a46fSAndroid Build Coastguard Worker
1786*3ac0a46fSAndroid Build Coastguard Worker auto* elem =
1787*3ac0a46fSAndroid Build Coastguard Worker notify_->GetFFDoc()->GetXMLDocument()->CreateNode<CFX_XMLElement>(
1788*3ac0a46fSAndroid Build Coastguard Worker wsDataTopLevelName);
1789*3ac0a46fSAndroid Build Coastguard Worker pDataTopLevel->SetXMLMappingNode(elem);
1790*3ac0a46fSAndroid Build Coastguard Worker
1791*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pBeforeNode = pDataRoot->GetFirstChild();
1792*3ac0a46fSAndroid Build Coastguard Worker pDataRoot->InsertChildAndNotify(pDataTopLevel, pBeforeNode);
1793*3ac0a46fSAndroid Build Coastguard Worker }
1794*3ac0a46fSAndroid Build Coastguard Worker
1795*3ac0a46fSAndroid Build Coastguard Worker DCHECK(pDataTopLevel);
1796*3ac0a46fSAndroid Build Coastguard Worker CreateDataBinding(pSubformSetNode, pDataTopLevel, true);
1797*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pTemplateChild = pTemplateChosen->GetFirstChild();
1798*3ac0a46fSAndroid Build Coastguard Worker pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
1799*3ac0a46fSAndroid Build Coastguard Worker if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) {
1800*3ac0a46fSAndroid Build Coastguard Worker XFA_NodeMerge_CloneOrMergeContainer(this, pSubformSetNode, pTemplateChild,
1801*3ac0a46fSAndroid Build Coastguard Worker true, nullptr);
1802*3ac0a46fSAndroid Build Coastguard Worker } else if (pTemplateChild->IsContainerNode()) {
1803*3ac0a46fSAndroid Build Coastguard Worker DataMerge_CopyContainer(pTemplateChild, pSubformSetNode, pDataTopLevel,
1804*3ac0a46fSAndroid Build Coastguard Worker false, true, true);
1805*3ac0a46fSAndroid Build Coastguard Worker }
1806*3ac0a46fSAndroid Build Coastguard Worker }
1807*3ac0a46fSAndroid Build Coastguard Worker if (pDDRoot)
1808*3ac0a46fSAndroid Build Coastguard Worker UpdateDataRelation(pDataRoot, pDDRoot);
1809*3ac0a46fSAndroid Build Coastguard Worker
1810*3ac0a46fSAndroid Build Coastguard Worker DataMerge_UpdateBindingRelations(pSubformSetNode);
1811*3ac0a46fSAndroid Build Coastguard Worker CXFA_PageSet* pPageSetNode =
1812*3ac0a46fSAndroid Build Coastguard Worker pSubformSetNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet);
1813*3ac0a46fSAndroid Build Coastguard Worker while (pPageSetNode) {
1814*3ac0a46fSAndroid Build Coastguard Worker m_pPendingPageSet.push_back(pPageSetNode);
1815*3ac0a46fSAndroid Build Coastguard Worker CXFA_PageSet* pNextPageSetNode =
1816*3ac0a46fSAndroid Build Coastguard Worker pPageSetNode->GetNextSameClassSibling<CXFA_PageSet>(
1817*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::PageSet);
1818*3ac0a46fSAndroid Build Coastguard Worker pSubformSetNode->RemoveChildAndNotify(pPageSetNode, true);
1819*3ac0a46fSAndroid Build Coastguard Worker pPageSetNode = pNextPageSetNode;
1820*3ac0a46fSAndroid Build Coastguard Worker }
1821*3ac0a46fSAndroid Build Coastguard Worker
1822*3ac0a46fSAndroid Build Coastguard Worker if (bEmptyForm)
1823*3ac0a46fSAndroid Build Coastguard Worker return;
1824*3ac0a46fSAndroid Build Coastguard Worker
1825*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(
1826*3ac0a46fSAndroid Build Coastguard Worker pFormRoot);
1827*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNode = sIterator.MoveToNext();
1828*3ac0a46fSAndroid Build Coastguard Worker while (pNode) {
1829*3ac0a46fSAndroid Build Coastguard Worker if (pNode->IsUnusedNode()) {
1830*3ac0a46fSAndroid Build Coastguard Worker if (pNode->IsContainerNode() ||
1831*3ac0a46fSAndroid Build Coastguard Worker pNode->GetElementType() == XFA_Element::InstanceManager) {
1832*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNext = sIterator.SkipChildrenAndMoveToNext();
1833*3ac0a46fSAndroid Build Coastguard Worker pNode->GetParent()->RemoveChildAndNotify(pNode, true);
1834*3ac0a46fSAndroid Build Coastguard Worker pNode = pNext;
1835*3ac0a46fSAndroid Build Coastguard Worker } else {
1836*3ac0a46fSAndroid Build Coastguard Worker pNode->ClearFlag(XFA_NodeFlag::kUnusedNode);
1837*3ac0a46fSAndroid Build Coastguard Worker pNode->SetInitializedFlagAndNotify();
1838*3ac0a46fSAndroid Build Coastguard Worker pNode = sIterator.MoveToNext();
1839*3ac0a46fSAndroid Build Coastguard Worker }
1840*3ac0a46fSAndroid Build Coastguard Worker } else {
1841*3ac0a46fSAndroid Build Coastguard Worker pNode->SetInitializedFlagAndNotify();
1842*3ac0a46fSAndroid Build Coastguard Worker pNode = sIterator.MoveToNext();
1843*3ac0a46fSAndroid Build Coastguard Worker }
1844*3ac0a46fSAndroid Build Coastguard Worker }
1845*3ac0a46fSAndroid Build Coastguard Worker }
1846*3ac0a46fSAndroid Build Coastguard Worker
DoDataRemerge()1847*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::DoDataRemerge() {
1848*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFormRoot = ToNode(GetXFAObject(XFA_HASHCODE_Form));
1849*3ac0a46fSAndroid Build Coastguard Worker if (pFormRoot) {
1850*3ac0a46fSAndroid Build Coastguard Worker while (CXFA_Node* pNode = pFormRoot->GetFirstChild())
1851*3ac0a46fSAndroid Build Coastguard Worker pFormRoot->RemoveChildAndNotify(pNode, true);
1852*3ac0a46fSAndroid Build Coastguard Worker
1853*3ac0a46fSAndroid Build Coastguard Worker pFormRoot->SetBindingNode(nullptr);
1854*3ac0a46fSAndroid Build Coastguard Worker }
1855*3ac0a46fSAndroid Build Coastguard Worker m_rgGlobalBinding.clear();
1856*3ac0a46fSAndroid Build Coastguard Worker DoDataMerge();
1857*3ac0a46fSAndroid Build Coastguard Worker GetLayoutProcessor()->SetForceRelayout();
1858*3ac0a46fSAndroid Build Coastguard Worker }
1859*3ac0a46fSAndroid Build Coastguard Worker
GetGlobalBinding(uint32_t dwNameHash)1860*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CXFA_Document::GetGlobalBinding(uint32_t dwNameHash) {
1861*3ac0a46fSAndroid Build Coastguard Worker auto it = m_rgGlobalBinding.find(dwNameHash);
1862*3ac0a46fSAndroid Build Coastguard Worker return it != m_rgGlobalBinding.end() ? it->second : nullptr;
1863*3ac0a46fSAndroid Build Coastguard Worker }
1864*3ac0a46fSAndroid Build Coastguard Worker
RegisterGlobalBinding(uint32_t dwNameHash,CXFA_Node * pDataNode)1865*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::RegisterGlobalBinding(uint32_t dwNameHash,
1866*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pDataNode) {
1867*3ac0a46fSAndroid Build Coastguard Worker m_rgGlobalBinding[dwNameHash] = pDataNode;
1868*3ac0a46fSAndroid Build Coastguard Worker }
1869*3ac0a46fSAndroid Build Coastguard Worker
GetPendingNodesCount() const1870*3ac0a46fSAndroid Build Coastguard Worker size_t CXFA_Document::GetPendingNodesCount() const {
1871*3ac0a46fSAndroid Build Coastguard Worker return m_pPendingPageSet.size();
1872*3ac0a46fSAndroid Build Coastguard Worker }
1873*3ac0a46fSAndroid Build Coastguard Worker
GetPendingNodeAtIndex(size_t index) const1874*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CXFA_Document::GetPendingNodeAtIndex(size_t index) const {
1875*3ac0a46fSAndroid Build Coastguard Worker return m_pPendingPageSet[index];
1876*3ac0a46fSAndroid Build Coastguard Worker }
1877*3ac0a46fSAndroid Build Coastguard Worker
AppendPendingNode(CXFA_Node * node)1878*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::AppendPendingNode(CXFA_Node* node) {
1879*3ac0a46fSAndroid Build Coastguard Worker m_pPendingPageSet.push_back(node);
1880*3ac0a46fSAndroid Build Coastguard Worker }
1881*3ac0a46fSAndroid Build Coastguard Worker
ClearPendingNodes()1882*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::ClearPendingNodes() {
1883*3ac0a46fSAndroid Build Coastguard Worker m_pPendingPageSet.clear();
1884*3ac0a46fSAndroid Build Coastguard Worker }
1885*3ac0a46fSAndroid Build Coastguard Worker
SetPendingNodesUnusedAndUnbound()1886*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::SetPendingNodesUnusedAndUnbound() {
1887*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pPageNode : m_pPendingPageSet) {
1888*3ac0a46fSAndroid Build Coastguard Worker CXFA_NodeIterator sIterator(pPageNode);
1889*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
1890*3ac0a46fSAndroid Build Coastguard Worker pNode = sIterator.MoveToNext()) {
1891*3ac0a46fSAndroid Build Coastguard Worker if (pNode->IsContainerNode()) {
1892*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pBindNode = pNode->GetBindData();
1893*3ac0a46fSAndroid Build Coastguard Worker if (pBindNode) {
1894*3ac0a46fSAndroid Build Coastguard Worker pBindNode->RemoveBindItem(pNode);
1895*3ac0a46fSAndroid Build Coastguard Worker pNode->SetBindingNode(nullptr);
1896*3ac0a46fSAndroid Build Coastguard Worker }
1897*3ac0a46fSAndroid Build Coastguard Worker }
1898*3ac0a46fSAndroid Build Coastguard Worker pNode->SetFlag(XFA_NodeFlag::kUnusedNode);
1899*3ac0a46fSAndroid Build Coastguard Worker }
1900*3ac0a46fSAndroid Build Coastguard Worker }
1901*3ac0a46fSAndroid Build Coastguard Worker }
1902*3ac0a46fSAndroid Build Coastguard Worker
1903*3ac0a46fSAndroid Build Coastguard Worker CXFA_Document::LayoutProcessorIface::LayoutProcessorIface() = default;
1904*3ac0a46fSAndroid Build Coastguard Worker
1905*3ac0a46fSAndroid Build Coastguard Worker CXFA_Document::LayoutProcessorIface::~LayoutProcessorIface() = default;
1906*3ac0a46fSAndroid Build Coastguard Worker
Trace(cppgc::Visitor * visitor) const1907*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Document::LayoutProcessorIface::Trace(cppgc::Visitor* visitor) const {
1908*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pDocument);
1909*3ac0a46fSAndroid Build Coastguard Worker }
1910