xref: /aosp_15_r20/external/pdfium/fxjs/xfa/cjx_node.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2017 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 "fxjs/xfa/cjx_node.h"
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include <memory>
10*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
11*3ac0a46fSAndroid Build Coastguard Worker #include <vector>
12*3ac0a46fSAndroid Build Coastguard Worker 
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/cfx_memorystream.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/cfx_read_only_string_stream.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_codepage.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmldocument.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmlelement.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmlparser.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/fxv8.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/js_resources.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_engine.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/v8-object.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_eventparam.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffdoc.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffnotify.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_document.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_document_builder.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_node.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_basic_data.h"
30*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_utils.h"
31*3ac0a46fSAndroid Build Coastguard Worker 
32*3ac0a46fSAndroid Build Coastguard Worker namespace {
33*3ac0a46fSAndroid Build Coastguard Worker 
34*3ac0a46fSAndroid Build Coastguard Worker enum class EventAppliesTo : uint8_t {
35*3ac0a46fSAndroid Build Coastguard Worker   kNone = 0,
36*3ac0a46fSAndroid Build Coastguard Worker   kAll = 1,
37*3ac0a46fSAndroid Build Coastguard Worker   kAllNonRecursive = 2,
38*3ac0a46fSAndroid Build Coastguard Worker   kSubform = 3,
39*3ac0a46fSAndroid Build Coastguard Worker   kFieldOrExclusion = 4,
40*3ac0a46fSAndroid Build Coastguard Worker   kField = 5,
41*3ac0a46fSAndroid Build Coastguard Worker   kSignature = 6,
42*3ac0a46fSAndroid Build Coastguard Worker   kChoiceList = 7
43*3ac0a46fSAndroid Build Coastguard Worker };
44*3ac0a46fSAndroid Build Coastguard Worker 
45*3ac0a46fSAndroid Build Coastguard Worker struct ExecEventParaInfo {
46*3ac0a46fSAndroid Build Coastguard Worker   uint32_t m_uHash;  // hashed as wide string.
47*3ac0a46fSAndroid Build Coastguard Worker   XFA_EVENTTYPE m_eventType;
48*3ac0a46fSAndroid Build Coastguard Worker   EventAppliesTo m_validFlags;
49*3ac0a46fSAndroid Build Coastguard Worker };
50*3ac0a46fSAndroid Build Coastguard Worker 
51*3ac0a46fSAndroid Build Coastguard Worker #undef PARA
52*3ac0a46fSAndroid Build Coastguard Worker #define PARA(a, b, c, d) a, c, EventAppliesTo::d
53*3ac0a46fSAndroid Build Coastguard Worker const ExecEventParaInfo kExecEventParaInfoTable[] = {
54*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0x109d7ce7, "mouseEnter", XFA_EVENT_MouseEnter, kField)},
55*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0x1bfc72d9, "preOpen", XFA_EVENT_PreOpen, kChoiceList)},
56*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0x2196a452, "initialize", XFA_EVENT_Initialize, kAll)},
57*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0x27410f03, "mouseExit", XFA_EVENT_MouseExit, kField)},
58*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0x36f1c6d8, "preSign", XFA_EVENT_PreSign, kSignature)},
59*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0x4731d6ba, "exit", XFA_EVENT_Exit, kAllNonRecursive)},
60*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0x7233018a, "validate", XFA_EVENT_Validate, kAll)},
61*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0x8808385e, "indexChange", XFA_EVENT_IndexChange, kSubform)},
62*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0x891f4606, "change", XFA_EVENT_Change, kFieldOrExclusion)},
63*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0x9f693b21, "mouseDown", XFA_EVENT_MouseDown, kField)},
64*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0xcdce56b3, "full", XFA_EVENT_Full, kFieldOrExclusion)},
65*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0xd576d08e, "mouseUp", XFA_EVENT_MouseUp, kField)},
66*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0xd95657a6, "click", XFA_EVENT_Click, kFieldOrExclusion)},
67*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0xdbfbe02e, "calculate", XFA_EVENT_Calculate, kAll)},
68*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0xe25fa7b8, "postOpen", XFA_EVENT_PostOpen, kChoiceList)},
69*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0xe28dce7e, "enter", XFA_EVENT_Enter, kAllNonRecursive)},
70*3ac0a46fSAndroid Build Coastguard Worker     {PARA(0xfd54fbb7, "postSign", XFA_EVENT_PostSign, kSignature)},
71*3ac0a46fSAndroid Build Coastguard Worker };
72*3ac0a46fSAndroid Build Coastguard Worker #undef PARA
73*3ac0a46fSAndroid Build Coastguard Worker 
GetExecEventParaInfoByName(WideStringView wsEventName)74*3ac0a46fSAndroid Build Coastguard Worker const ExecEventParaInfo* GetExecEventParaInfoByName(
75*3ac0a46fSAndroid Build Coastguard Worker     WideStringView wsEventName) {
76*3ac0a46fSAndroid Build Coastguard Worker   if (wsEventName.IsEmpty())
77*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
78*3ac0a46fSAndroid Build Coastguard Worker 
79*3ac0a46fSAndroid Build Coastguard Worker   uint32_t uHash = FX_HashCode_GetW(wsEventName);
80*3ac0a46fSAndroid Build Coastguard Worker   auto* result = std::lower_bound(
81*3ac0a46fSAndroid Build Coastguard Worker       std::begin(kExecEventParaInfoTable), std::end(kExecEventParaInfoTable),
82*3ac0a46fSAndroid Build Coastguard Worker       uHash, [](const ExecEventParaInfo& iter, const uint16_t& hash) {
83*3ac0a46fSAndroid Build Coastguard Worker         return iter.m_uHash < hash;
84*3ac0a46fSAndroid Build Coastguard Worker       });
85*3ac0a46fSAndroid Build Coastguard Worker   if (result != std::end(kExecEventParaInfoTable) && result->m_uHash == uHash)
86*3ac0a46fSAndroid Build Coastguard Worker     return result;
87*3ac0a46fSAndroid Build Coastguard Worker   return nullptr;
88*3ac0a46fSAndroid Build Coastguard Worker }
89*3ac0a46fSAndroid Build Coastguard Worker 
90*3ac0a46fSAndroid Build Coastguard Worker }  // namespace
91*3ac0a46fSAndroid Build Coastguard Worker 
92*3ac0a46fSAndroid Build Coastguard Worker const CJX_MethodSpec CJX_Node::MethodSpecs[] = {
93*3ac0a46fSAndroid Build Coastguard Worker     {"applyXSL", applyXSL_static},
94*3ac0a46fSAndroid Build Coastguard Worker     {"assignNode", assignNode_static},
95*3ac0a46fSAndroid Build Coastguard Worker     {"clone", clone_static},
96*3ac0a46fSAndroid Build Coastguard Worker     {"getAttribute", getAttribute_static},
97*3ac0a46fSAndroid Build Coastguard Worker     {"getElement", getElement_static},
98*3ac0a46fSAndroid Build Coastguard Worker     {"isPropertySpecified", isPropertySpecified_static},
99*3ac0a46fSAndroid Build Coastguard Worker     {"loadXML", loadXML_static},
100*3ac0a46fSAndroid Build Coastguard Worker     {"saveFilteredXML", saveFilteredXML_static},
101*3ac0a46fSAndroid Build Coastguard Worker     {"saveXML", saveXML_static},
102*3ac0a46fSAndroid Build Coastguard Worker     {"setAttribute", setAttribute_static},
103*3ac0a46fSAndroid Build Coastguard Worker     {"setElement", setElement_static}};
104*3ac0a46fSAndroid Build Coastguard Worker 
CJX_Node(CXFA_Node * node)105*3ac0a46fSAndroid Build Coastguard Worker CJX_Node::CJX_Node(CXFA_Node* node) : CJX_Tree(node) {
106*3ac0a46fSAndroid Build Coastguard Worker   DefineMethods(MethodSpecs);
107*3ac0a46fSAndroid Build Coastguard Worker }
108*3ac0a46fSAndroid Build Coastguard Worker 
109*3ac0a46fSAndroid Build Coastguard Worker CJX_Node::~CJX_Node() = default;
110*3ac0a46fSAndroid Build Coastguard Worker 
DynamicTypeIs(TypeTag eType) const111*3ac0a46fSAndroid Build Coastguard Worker bool CJX_Node::DynamicTypeIs(TypeTag eType) const {
112*3ac0a46fSAndroid Build Coastguard Worker   return eType == static_type__ || ParentType__::DynamicTypeIs(eType);
113*3ac0a46fSAndroid Build Coastguard Worker }
114*3ac0a46fSAndroid Build Coastguard Worker 
applyXSL(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)115*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Node::applyXSL(CFXJSE_Engine* runtime,
116*3ac0a46fSAndroid Build Coastguard Worker                               const std::vector<v8::Local<v8::Value>>& params) {
117*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() != 1)
118*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
119*3ac0a46fSAndroid Build Coastguard Worker 
120*3ac0a46fSAndroid Build Coastguard Worker   // TODO(weili): check whether we need to implement this, pdfium:501.
121*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success();
122*3ac0a46fSAndroid Build Coastguard Worker }
123*3ac0a46fSAndroid Build Coastguard Worker 
assignNode(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)124*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Node::assignNode(
125*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
126*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
127*3ac0a46fSAndroid Build Coastguard Worker   if (params.empty() || params.size() > 3)
128*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
129*3ac0a46fSAndroid Build Coastguard Worker 
130*3ac0a46fSAndroid Build Coastguard Worker   // TODO(weili): check whether we need to implement this, pdfium:501.
131*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success();
132*3ac0a46fSAndroid Build Coastguard Worker }
133*3ac0a46fSAndroid Build Coastguard Worker 
clone(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)134*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Node::clone(CFXJSE_Engine* runtime,
135*3ac0a46fSAndroid Build Coastguard Worker                            const std::vector<v8::Local<v8::Value>>& params) {
136*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() != 1)
137*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
138*3ac0a46fSAndroid Build Coastguard Worker 
139*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pCloneNode = GetXFANode()->Clone(runtime->ToBoolean(params[0]));
140*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->GetOrCreateJSBindingFromMap(pCloneNode));
141*3ac0a46fSAndroid Build Coastguard Worker }
142*3ac0a46fSAndroid Build Coastguard Worker 
getAttribute(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)143*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Node::getAttribute(
144*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
145*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
146*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() != 1)
147*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
148*3ac0a46fSAndroid Build Coastguard Worker 
149*3ac0a46fSAndroid Build Coastguard Worker   WideString expression = runtime->ToWideString(params[0]);
150*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->NewString(
151*3ac0a46fSAndroid Build Coastguard Worker       GetAttributeByString(expression.AsStringView()).ToUTF8().AsStringView()));
152*3ac0a46fSAndroid Build Coastguard Worker }
153*3ac0a46fSAndroid Build Coastguard Worker 
getElement(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)154*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Node::getElement(
155*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
156*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
157*3ac0a46fSAndroid Build Coastguard Worker   if (params.empty() || params.size() > 2)
158*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
159*3ac0a46fSAndroid Build Coastguard Worker 
160*3ac0a46fSAndroid Build Coastguard Worker   WideString expression = runtime->ToWideString(params[0]);
161*3ac0a46fSAndroid Build Coastguard Worker   int32_t iValue = params.size() >= 2 ? runtime->ToInt32(params[1]) : 0;
162*3ac0a46fSAndroid Build Coastguard Worker   XFA_Element eElement = XFA_GetElementByName(expression.AsStringView());
163*3ac0a46fSAndroid Build Coastguard Worker   if (eElement == XFA_Element::Unknown)
164*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success(runtime->NewNull());
165*3ac0a46fSAndroid Build Coastguard Worker 
166*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pNode = GetOrCreateProperty<CXFA_Node>(iValue, eElement);
167*3ac0a46fSAndroid Build Coastguard Worker   if (!pNode)
168*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success(runtime->NewNull());
169*3ac0a46fSAndroid Build Coastguard Worker 
170*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->GetOrCreateJSBindingFromMap(pNode));
171*3ac0a46fSAndroid Build Coastguard Worker }
172*3ac0a46fSAndroid Build Coastguard Worker 
isPropertySpecified(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)173*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Node::isPropertySpecified(
174*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
175*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
176*3ac0a46fSAndroid Build Coastguard Worker   if (params.empty() || params.size() > 3)
177*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
178*3ac0a46fSAndroid Build Coastguard Worker 
179*3ac0a46fSAndroid Build Coastguard Worker   WideString expression = runtime->ToWideString(params[0]);
180*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<XFA_ATTRIBUTEINFO> attr =
181*3ac0a46fSAndroid Build Coastguard Worker       XFA_GetAttributeByName(expression.AsStringView());
182*3ac0a46fSAndroid Build Coastguard Worker   if (attr.has_value() && HasAttribute(attr.value().attribute))
183*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success(runtime->NewBoolean(true));
184*3ac0a46fSAndroid Build Coastguard Worker 
185*3ac0a46fSAndroid Build Coastguard Worker   XFA_Element eType = XFA_GetElementByName(expression.AsStringView());
186*3ac0a46fSAndroid Build Coastguard Worker   if (eType == XFA_Element::Unknown)
187*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success(runtime->NewBoolean(false));
188*3ac0a46fSAndroid Build Coastguard Worker 
189*3ac0a46fSAndroid Build Coastguard Worker   bool bParent = params.size() < 2 || runtime->ToBoolean(params[1]);
190*3ac0a46fSAndroid Build Coastguard Worker   int32_t iIndex = params.size() == 3 ? runtime->ToInt32(params[2]) : 0;
191*3ac0a46fSAndroid Build Coastguard Worker   bool bHas = !!GetOrCreateProperty<CXFA_Node>(iIndex, eType);
192*3ac0a46fSAndroid Build Coastguard Worker   if (!bHas && bParent && GetXFANode()->GetParent()) {
193*3ac0a46fSAndroid Build Coastguard Worker     // Also check on the parent.
194*3ac0a46fSAndroid Build Coastguard Worker     auto* jsnode = GetXFANode()->GetParent()->JSObject();
195*3ac0a46fSAndroid Build Coastguard Worker     bHas = jsnode->HasAttribute(attr.value().attribute) ||
196*3ac0a46fSAndroid Build Coastguard Worker            !!jsnode->GetOrCreateProperty<CXFA_Node>(iIndex, eType);
197*3ac0a46fSAndroid Build Coastguard Worker   }
198*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(runtime->NewBoolean(bHas));
199*3ac0a46fSAndroid Build Coastguard Worker }
200*3ac0a46fSAndroid Build Coastguard Worker 
loadXML(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)201*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Node::loadXML(CFXJSE_Engine* runtime,
202*3ac0a46fSAndroid Build Coastguard Worker                              const std::vector<v8::Local<v8::Value>>& params) {
203*3ac0a46fSAndroid Build Coastguard Worker   if (params.empty() || params.size() > 3)
204*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
205*3ac0a46fSAndroid Build Coastguard Worker 
206*3ac0a46fSAndroid Build Coastguard Worker   ByteString expression = runtime->ToByteString(params[0]);
207*3ac0a46fSAndroid Build Coastguard Worker   if (expression.IsEmpty())
208*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success();
209*3ac0a46fSAndroid Build Coastguard Worker 
210*3ac0a46fSAndroid Build Coastguard Worker   bool bIgnoreRoot = true;
211*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() >= 2)
212*3ac0a46fSAndroid Build Coastguard Worker     bIgnoreRoot = runtime->ToBoolean(params[1]);
213*3ac0a46fSAndroid Build Coastguard Worker 
214*3ac0a46fSAndroid Build Coastguard Worker   bool bOverwrite = false;
215*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() >= 3)
216*3ac0a46fSAndroid Build Coastguard Worker     bOverwrite = runtime->ToBoolean(params[2]);
217*3ac0a46fSAndroid Build Coastguard Worker 
218*3ac0a46fSAndroid Build Coastguard Worker   auto stream =
219*3ac0a46fSAndroid Build Coastguard Worker       pdfium::MakeRetain<CFX_ReadOnlyStringStream>(std::move(expression));
220*3ac0a46fSAndroid Build Coastguard Worker 
221*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLParser parser(stream);
222*3ac0a46fSAndroid Build Coastguard Worker   std::unique_ptr<CFX_XMLDocument> xml_doc = parser.Parse();
223*3ac0a46fSAndroid Build Coastguard Worker   CXFA_DocumentBuilder builder(GetDocument());
224*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLNode* pXMLNode = builder.Build(xml_doc.get());
225*3ac0a46fSAndroid Build Coastguard Worker   if (!pXMLNode)
226*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success();
227*3ac0a46fSAndroid Build Coastguard Worker 
228*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLDocument* top_xml_doc =
229*3ac0a46fSAndroid Build Coastguard Worker       GetXFANode()->GetDocument()->GetNotify()->GetFFDoc()->GetXMLDocument();
230*3ac0a46fSAndroid Build Coastguard Worker   top_xml_doc->AppendNodesFrom(xml_doc.get());
231*3ac0a46fSAndroid Build Coastguard Worker 
232*3ac0a46fSAndroid Build Coastguard Worker   if (bIgnoreRoot &&
233*3ac0a46fSAndroid Build Coastguard Worker       (pXMLNode->GetType() != CFX_XMLNode::Type::kElement ||
234*3ac0a46fSAndroid Build Coastguard Worker        XFA_RecognizeRichText(static_cast<CFX_XMLElement*>(pXMLNode)))) {
235*3ac0a46fSAndroid Build Coastguard Worker     bIgnoreRoot = false;
236*3ac0a46fSAndroid Build Coastguard Worker   }
237*3ac0a46fSAndroid Build Coastguard Worker 
238*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pFakeRoot = GetXFANode()->Clone(false);
239*3ac0a46fSAndroid Build Coastguard Worker   WideString wsContentType = GetCData(XFA_Attribute::ContentType);
240*3ac0a46fSAndroid Build Coastguard Worker   if (!wsContentType.IsEmpty()) {
241*3ac0a46fSAndroid Build Coastguard Worker     pFakeRoot->JSObject()->SetCData(XFA_Attribute::ContentType,
242*3ac0a46fSAndroid Build Coastguard Worker                                     WideString(wsContentType));
243*3ac0a46fSAndroid Build Coastguard Worker   }
244*3ac0a46fSAndroid Build Coastguard Worker 
245*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLNode* pFakeXMLRoot = pFakeRoot->GetXMLMappingNode();
246*3ac0a46fSAndroid Build Coastguard Worker   if (!pFakeXMLRoot) {
247*3ac0a46fSAndroid Build Coastguard Worker     CFX_XMLNode* pThisXMLRoot = GetXFANode()->GetXMLMappingNode();
248*3ac0a46fSAndroid Build Coastguard Worker     CFX_XMLNode* clone;
249*3ac0a46fSAndroid Build Coastguard Worker     if (pThisXMLRoot) {
250*3ac0a46fSAndroid Build Coastguard Worker       clone = pThisXMLRoot->Clone(top_xml_doc);
251*3ac0a46fSAndroid Build Coastguard Worker     } else {
252*3ac0a46fSAndroid Build Coastguard Worker       clone = top_xml_doc->CreateNode<CFX_XMLElement>(
253*3ac0a46fSAndroid Build Coastguard Worker           WideString::FromASCII(GetXFANode()->GetClassName()));
254*3ac0a46fSAndroid Build Coastguard Worker     }
255*3ac0a46fSAndroid Build Coastguard Worker     pFakeXMLRoot = clone;
256*3ac0a46fSAndroid Build Coastguard Worker   }
257*3ac0a46fSAndroid Build Coastguard Worker 
258*3ac0a46fSAndroid Build Coastguard Worker   if (bIgnoreRoot) {
259*3ac0a46fSAndroid Build Coastguard Worker     CFX_XMLNode* pXMLChild = pXMLNode->GetFirstChild();
260*3ac0a46fSAndroid Build Coastguard Worker     while (pXMLChild) {
261*3ac0a46fSAndroid Build Coastguard Worker       CFX_XMLNode* pXMLSibling = pXMLChild->GetNextSibling();
262*3ac0a46fSAndroid Build Coastguard Worker       pXMLNode->RemoveChild(pXMLChild);
263*3ac0a46fSAndroid Build Coastguard Worker       pFakeXMLRoot->AppendLastChild(pXMLChild);
264*3ac0a46fSAndroid Build Coastguard Worker       pXMLChild = pXMLSibling;
265*3ac0a46fSAndroid Build Coastguard Worker     }
266*3ac0a46fSAndroid Build Coastguard Worker   } else {
267*3ac0a46fSAndroid Build Coastguard Worker     pXMLNode->RemoveSelfIfParented();
268*3ac0a46fSAndroid Build Coastguard Worker     pFakeXMLRoot->AppendLastChild(pXMLNode);
269*3ac0a46fSAndroid Build Coastguard Worker   }
270*3ac0a46fSAndroid Build Coastguard Worker 
271*3ac0a46fSAndroid Build Coastguard Worker   builder.ConstructXFANode(pFakeRoot, pFakeXMLRoot);
272*3ac0a46fSAndroid Build Coastguard Worker   pFakeRoot = builder.GetRootNode();
273*3ac0a46fSAndroid Build Coastguard Worker   if (!pFakeRoot)
274*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success();
275*3ac0a46fSAndroid Build Coastguard Worker 
276*3ac0a46fSAndroid Build Coastguard Worker   if (bOverwrite) {
277*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Node* pChild = GetXFANode()->GetFirstChild();
278*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Node* pNewChild = pFakeRoot->GetFirstChild();
279*3ac0a46fSAndroid Build Coastguard Worker     int32_t index = 0;
280*3ac0a46fSAndroid Build Coastguard Worker     while (pNewChild) {
281*3ac0a46fSAndroid Build Coastguard Worker       CXFA_Node* pItem = pNewChild->GetNextSibling();
282*3ac0a46fSAndroid Build Coastguard Worker       pFakeRoot->RemoveChildAndNotify(pNewChild, true);
283*3ac0a46fSAndroid Build Coastguard Worker       GetXFANode()->InsertChildAndNotify(index++, pNewChild);
284*3ac0a46fSAndroid Build Coastguard Worker       pNewChild->SetInitializedFlagAndNotify();
285*3ac0a46fSAndroid Build Coastguard Worker       pNewChild = pItem;
286*3ac0a46fSAndroid Build Coastguard Worker     }
287*3ac0a46fSAndroid Build Coastguard Worker 
288*3ac0a46fSAndroid Build Coastguard Worker     while (pChild) {
289*3ac0a46fSAndroid Build Coastguard Worker       CXFA_Node* pItem = pChild->GetNextSibling();
290*3ac0a46fSAndroid Build Coastguard Worker       GetXFANode()->RemoveChildAndNotify(pChild, true);
291*3ac0a46fSAndroid Build Coastguard Worker       pFakeRoot->InsertChildAndNotify(pChild, nullptr);
292*3ac0a46fSAndroid Build Coastguard Worker       pChild = pItem;
293*3ac0a46fSAndroid Build Coastguard Worker     }
294*3ac0a46fSAndroid Build Coastguard Worker 
295*3ac0a46fSAndroid Build Coastguard Worker     if (GetXFANode()->GetPacketType() == XFA_PacketType::Form &&
296*3ac0a46fSAndroid Build Coastguard Worker         GetXFANode()->GetElementType() == XFA_Element::ExData) {
297*3ac0a46fSAndroid Build Coastguard Worker       CFX_XMLNode* pTempXMLNode = GetXFANode()->GetXMLMappingNode();
298*3ac0a46fSAndroid Build Coastguard Worker       GetXFANode()->SetXMLMappingNode(pFakeXMLRoot);
299*3ac0a46fSAndroid Build Coastguard Worker 
300*3ac0a46fSAndroid Build Coastguard Worker       if (pTempXMLNode && !pTempXMLNode->GetParent())
301*3ac0a46fSAndroid Build Coastguard Worker         pFakeXMLRoot = pTempXMLNode;
302*3ac0a46fSAndroid Build Coastguard Worker       else
303*3ac0a46fSAndroid Build Coastguard Worker         pFakeXMLRoot = nullptr;
304*3ac0a46fSAndroid Build Coastguard Worker     }
305*3ac0a46fSAndroid Build Coastguard Worker     MoveBufferMapData(pFakeRoot, GetXFANode());
306*3ac0a46fSAndroid Build Coastguard Worker   } else {
307*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Node* pChild = pFakeRoot->GetFirstChild();
308*3ac0a46fSAndroid Build Coastguard Worker     while (pChild) {
309*3ac0a46fSAndroid Build Coastguard Worker       CXFA_Node* pItem = pChild->GetNextSibling();
310*3ac0a46fSAndroid Build Coastguard Worker       pFakeRoot->RemoveChildAndNotify(pChild, true);
311*3ac0a46fSAndroid Build Coastguard Worker       GetXFANode()->InsertChildAndNotify(pChild, nullptr);
312*3ac0a46fSAndroid Build Coastguard Worker       pChild->SetInitializedFlagAndNotify();
313*3ac0a46fSAndroid Build Coastguard Worker       pChild = pItem;
314*3ac0a46fSAndroid Build Coastguard Worker     }
315*3ac0a46fSAndroid Build Coastguard Worker   }
316*3ac0a46fSAndroid Build Coastguard Worker 
317*3ac0a46fSAndroid Build Coastguard Worker   if (pFakeXMLRoot) {
318*3ac0a46fSAndroid Build Coastguard Worker     pFakeRoot->SetXMLMappingNode(std::move(pFakeXMLRoot));
319*3ac0a46fSAndroid Build Coastguard Worker   }
320*3ac0a46fSAndroid Build Coastguard Worker   pFakeRoot->SetFlag(XFA_NodeFlag::kHasRemovedChildren);
321*3ac0a46fSAndroid Build Coastguard Worker 
322*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success();
323*3ac0a46fSAndroid Build Coastguard Worker }
324*3ac0a46fSAndroid Build Coastguard Worker 
saveFilteredXML(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)325*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Node::saveFilteredXML(
326*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
327*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
328*3ac0a46fSAndroid Build Coastguard Worker   // TODO(weili): Check whether we need to implement this, pdfium:501.
329*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success();
330*3ac0a46fSAndroid Build Coastguard Worker }
331*3ac0a46fSAndroid Build Coastguard Worker 
saveXML(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)332*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Node::saveXML(CFXJSE_Engine* runtime,
333*3ac0a46fSAndroid Build Coastguard Worker                              const std::vector<v8::Local<v8::Value>>& params) {
334*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() > 1)
335*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
336*3ac0a46fSAndroid Build Coastguard Worker 
337*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() == 1 &&
338*3ac0a46fSAndroid Build Coastguard Worker       !runtime->ToWideString(params[0]).EqualsASCII("pretty")) {
339*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kValueError);
340*3ac0a46fSAndroid Build Coastguard Worker   }
341*3ac0a46fSAndroid Build Coastguard Worker 
342*3ac0a46fSAndroid Build Coastguard Worker   // TODO(weili): Check whether we need to save pretty print XML, pdfium:501.
343*3ac0a46fSAndroid Build Coastguard Worker 
344*3ac0a46fSAndroid Build Coastguard Worker   ByteString bsXMLHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
345*3ac0a46fSAndroid Build Coastguard Worker   if (GetXFANode()->GetPacketType() != XFA_PacketType::Form &&
346*3ac0a46fSAndroid Build Coastguard Worker       GetXFANode()->GetPacketType() != XFA_PacketType::Datasets) {
347*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Success(runtime->NewString(""));
348*3ac0a46fSAndroid Build Coastguard Worker   }
349*3ac0a46fSAndroid Build Coastguard Worker 
350*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLNode* pElement = nullptr;
351*3ac0a46fSAndroid Build Coastguard Worker   if (GetXFANode()->GetPacketType() == XFA_PacketType::Datasets) {
352*3ac0a46fSAndroid Build Coastguard Worker     pElement = GetXFANode()->GetXMLMappingNode();
353*3ac0a46fSAndroid Build Coastguard Worker     if (!pElement || pElement->GetType() != CFX_XMLNode::Type::kElement) {
354*3ac0a46fSAndroid Build Coastguard Worker       return CJS_Result::Success(
355*3ac0a46fSAndroid Build Coastguard Worker           runtime->NewString(bsXMLHeader.AsStringView()));
356*3ac0a46fSAndroid Build Coastguard Worker     }
357*3ac0a46fSAndroid Build Coastguard Worker 
358*3ac0a46fSAndroid Build Coastguard Worker     XFA_DataExporter_DealWithDataGroupNode(GetXFANode());
359*3ac0a46fSAndroid Build Coastguard Worker   }
360*3ac0a46fSAndroid Build Coastguard Worker 
361*3ac0a46fSAndroid Build Coastguard Worker   auto pMemoryStream = pdfium::MakeRetain<CFX_MemoryStream>();
362*3ac0a46fSAndroid Build Coastguard Worker   pMemoryStream->WriteString(bsXMLHeader.AsStringView());
363*3ac0a46fSAndroid Build Coastguard Worker 
364*3ac0a46fSAndroid Build Coastguard Worker   if (GetXFANode()->GetPacketType() == XFA_PacketType::Form) {
365*3ac0a46fSAndroid Build Coastguard Worker     XFA_DataExporter_RegenerateFormFile(GetXFANode(), pMemoryStream, true);
366*3ac0a46fSAndroid Build Coastguard Worker   } else {
367*3ac0a46fSAndroid Build Coastguard Worker     pElement->Save(pMemoryStream);
368*3ac0a46fSAndroid Build Coastguard Worker   }
369*3ac0a46fSAndroid Build Coastguard Worker 
370*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success(
371*3ac0a46fSAndroid Build Coastguard Worker       runtime->NewString(ByteStringView(pMemoryStream->GetSpan())));
372*3ac0a46fSAndroid Build Coastguard Worker }
373*3ac0a46fSAndroid Build Coastguard Worker 
setAttribute(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)374*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Node::setAttribute(
375*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
376*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
377*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() != 2)
378*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
379*3ac0a46fSAndroid Build Coastguard Worker 
380*3ac0a46fSAndroid Build Coastguard Worker   // Note: yes, arglist is spec'd absolutely backwards from what any sane
381*3ac0a46fSAndroid Build Coastguard Worker   // person would do, namely value first, attribute second.
382*3ac0a46fSAndroid Build Coastguard Worker   WideString attributeValue = runtime->ToWideString(params[0]);
383*3ac0a46fSAndroid Build Coastguard Worker   WideString attribute = runtime->ToWideString(params[1]);
384*3ac0a46fSAndroid Build Coastguard Worker 
385*3ac0a46fSAndroid Build Coastguard Worker   // Pass them to our method, however, in the more usual manner.
386*3ac0a46fSAndroid Build Coastguard Worker   SetAttributeByString(attribute.AsStringView(), attributeValue);
387*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success();
388*3ac0a46fSAndroid Build Coastguard Worker }
389*3ac0a46fSAndroid Build Coastguard Worker 
setElement(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)390*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CJX_Node::setElement(
391*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine* runtime,
392*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<v8::Local<v8::Value>>& params) {
393*3ac0a46fSAndroid Build Coastguard Worker   if (params.size() != 1 && params.size() != 2)
394*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(JSMessage::kParamError);
395*3ac0a46fSAndroid Build Coastguard Worker 
396*3ac0a46fSAndroid Build Coastguard Worker   // TODO(weili): check whether we need to implement this, pdfium:501.
397*3ac0a46fSAndroid Build Coastguard Worker   return CJS_Result::Success();
398*3ac0a46fSAndroid Build Coastguard Worker }
399*3ac0a46fSAndroid Build Coastguard Worker 
ns(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)400*3ac0a46fSAndroid Build Coastguard Worker void CJX_Node::ns(v8::Isolate* pIsolate,
401*3ac0a46fSAndroid Build Coastguard Worker                   v8::Local<v8::Value>* pValue,
402*3ac0a46fSAndroid Build Coastguard Worker                   bool bSetting,
403*3ac0a46fSAndroid Build Coastguard Worker                   XFA_Attribute eAttribute) {
404*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
405*3ac0a46fSAndroid Build Coastguard Worker     ThrowInvalidPropertyException(pIsolate);
406*3ac0a46fSAndroid Build Coastguard Worker     return;
407*3ac0a46fSAndroid Build Coastguard Worker   }
408*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewStringHelper(
409*3ac0a46fSAndroid Build Coastguard Worker       pIsolate, TryNamespace().value_or(WideString()).ToUTF8().AsStringView());
410*3ac0a46fSAndroid Build Coastguard Worker }
411*3ac0a46fSAndroid Build Coastguard Worker 
model(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)412*3ac0a46fSAndroid Build Coastguard Worker void CJX_Node::model(v8::Isolate* pIsolate,
413*3ac0a46fSAndroid Build Coastguard Worker                      v8::Local<v8::Value>* pValue,
414*3ac0a46fSAndroid Build Coastguard Worker                      bool bSetting,
415*3ac0a46fSAndroid Build Coastguard Worker                      XFA_Attribute eAttribute) {
416*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
417*3ac0a46fSAndroid Build Coastguard Worker     ThrowInvalidPropertyException(pIsolate);
418*3ac0a46fSAndroid Build Coastguard Worker     return;
419*3ac0a46fSAndroid Build Coastguard Worker   }
420*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pModel = GetXFANode()->GetModelNode();
421*3ac0a46fSAndroid Build Coastguard Worker   if (!pModel) {
422*3ac0a46fSAndroid Build Coastguard Worker     *pValue = fxv8::NewNullHelper(pIsolate);
423*3ac0a46fSAndroid Build Coastguard Worker     return;
424*3ac0a46fSAndroid Build Coastguard Worker   }
425*3ac0a46fSAndroid Build Coastguard Worker   *pValue =
426*3ac0a46fSAndroid Build Coastguard Worker       GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pModel);
427*3ac0a46fSAndroid Build Coastguard Worker }
428*3ac0a46fSAndroid Build Coastguard Worker 
isContainer(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)429*3ac0a46fSAndroid Build Coastguard Worker void CJX_Node::isContainer(v8::Isolate* pIsolate,
430*3ac0a46fSAndroid Build Coastguard Worker                            v8::Local<v8::Value>* pValue,
431*3ac0a46fSAndroid Build Coastguard Worker                            bool bSetting,
432*3ac0a46fSAndroid Build Coastguard Worker                            XFA_Attribute eAttribute) {
433*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
434*3ac0a46fSAndroid Build Coastguard Worker     ThrowInvalidPropertyException(pIsolate);
435*3ac0a46fSAndroid Build Coastguard Worker     return;
436*3ac0a46fSAndroid Build Coastguard Worker   }
437*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewBooleanHelper(pIsolate, GetXFANode()->IsContainerNode());
438*3ac0a46fSAndroid Build Coastguard Worker }
439*3ac0a46fSAndroid Build Coastguard Worker 
isNull(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)440*3ac0a46fSAndroid Build Coastguard Worker void CJX_Node::isNull(v8::Isolate* pIsolate,
441*3ac0a46fSAndroid Build Coastguard Worker                       v8::Local<v8::Value>* pValue,
442*3ac0a46fSAndroid Build Coastguard Worker                       bool bSetting,
443*3ac0a46fSAndroid Build Coastguard Worker                       XFA_Attribute eAttribute) {
444*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
445*3ac0a46fSAndroid Build Coastguard Worker     ThrowInvalidPropertyException(pIsolate);
446*3ac0a46fSAndroid Build Coastguard Worker     return;
447*3ac0a46fSAndroid Build Coastguard Worker   }
448*3ac0a46fSAndroid Build Coastguard Worker   if (GetXFANode()->GetElementType() == XFA_Element::Subform) {
449*3ac0a46fSAndroid Build Coastguard Worker     *pValue = fxv8::NewBooleanHelper(pIsolate, false);
450*3ac0a46fSAndroid Build Coastguard Worker     return;
451*3ac0a46fSAndroid Build Coastguard Worker   }
452*3ac0a46fSAndroid Build Coastguard Worker   *pValue = fxv8::NewBooleanHelper(pIsolate, GetContent(false).IsEmpty());
453*3ac0a46fSAndroid Build Coastguard Worker }
454*3ac0a46fSAndroid Build Coastguard Worker 
oneOfChild(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)455*3ac0a46fSAndroid Build Coastguard Worker void CJX_Node::oneOfChild(v8::Isolate* pIsolate,
456*3ac0a46fSAndroid Build Coastguard Worker                           v8::Local<v8::Value>* pValue,
457*3ac0a46fSAndroid Build Coastguard Worker                           bool bSetting,
458*3ac0a46fSAndroid Build Coastguard Worker                           XFA_Attribute eAttribute) {
459*3ac0a46fSAndroid Build Coastguard Worker   if (bSetting) {
460*3ac0a46fSAndroid Build Coastguard Worker     ThrowInvalidPropertyException(pIsolate);
461*3ac0a46fSAndroid Build Coastguard Worker     return;
462*3ac0a46fSAndroid Build Coastguard Worker   }
463*3ac0a46fSAndroid Build Coastguard Worker 
464*3ac0a46fSAndroid Build Coastguard Worker   std::vector<CXFA_Node*> properties =
465*3ac0a46fSAndroid Build Coastguard Worker       GetXFANode()->GetNodeListWithFilter(XFA_NodeFilter::kOneOfProperty);
466*3ac0a46fSAndroid Build Coastguard Worker   if (!properties.empty()) {
467*3ac0a46fSAndroid Build Coastguard Worker     *pValue = GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
468*3ac0a46fSAndroid Build Coastguard Worker         properties.front());
469*3ac0a46fSAndroid Build Coastguard Worker   }
470*3ac0a46fSAndroid Build Coastguard Worker }
471*3ac0a46fSAndroid Build Coastguard Worker 
execSingleEventByName(WideStringView wsEventName,XFA_Element eType)472*3ac0a46fSAndroid Build Coastguard Worker XFA_EventError CJX_Node::execSingleEventByName(WideStringView wsEventName,
473*3ac0a46fSAndroid Build Coastguard Worker                                                XFA_Element eType) {
474*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
475*3ac0a46fSAndroid Build Coastguard Worker   if (!pNotify)
476*3ac0a46fSAndroid Build Coastguard Worker     return XFA_EventError::kNotExist;
477*3ac0a46fSAndroid Build Coastguard Worker 
478*3ac0a46fSAndroid Build Coastguard Worker   const ExecEventParaInfo* eventParaInfo =
479*3ac0a46fSAndroid Build Coastguard Worker       GetExecEventParaInfoByName(wsEventName);
480*3ac0a46fSAndroid Build Coastguard Worker   if (!eventParaInfo)
481*3ac0a46fSAndroid Build Coastguard Worker     return XFA_EventError::kNotExist;
482*3ac0a46fSAndroid Build Coastguard Worker 
483*3ac0a46fSAndroid Build Coastguard Worker   switch (eventParaInfo->m_validFlags) {
484*3ac0a46fSAndroid Build Coastguard Worker     case EventAppliesTo::kNone:
485*3ac0a46fSAndroid Build Coastguard Worker       return XFA_EventError::kNotExist;
486*3ac0a46fSAndroid Build Coastguard Worker     case EventAppliesTo::kAll:
487*3ac0a46fSAndroid Build Coastguard Worker     case EventAppliesTo::kAllNonRecursive:
488*3ac0a46fSAndroid Build Coastguard Worker       return pNotify->ExecEventByDeepFirst(
489*3ac0a46fSAndroid Build Coastguard Worker           GetXFANode(), eventParaInfo->m_eventType, false,
490*3ac0a46fSAndroid Build Coastguard Worker           eventParaInfo->m_validFlags == EventAppliesTo::kAll);
491*3ac0a46fSAndroid Build Coastguard Worker     case EventAppliesTo::kSubform:
492*3ac0a46fSAndroid Build Coastguard Worker       if (eType != XFA_Element::Subform)
493*3ac0a46fSAndroid Build Coastguard Worker         return XFA_EventError::kNotExist;
494*3ac0a46fSAndroid Build Coastguard Worker 
495*3ac0a46fSAndroid Build Coastguard Worker       return pNotify->ExecEventByDeepFirst(
496*3ac0a46fSAndroid Build Coastguard Worker           GetXFANode(), eventParaInfo->m_eventType, false, false);
497*3ac0a46fSAndroid Build Coastguard Worker     case EventAppliesTo::kFieldOrExclusion: {
498*3ac0a46fSAndroid Build Coastguard Worker       if (eType != XFA_Element::ExclGroup && eType != XFA_Element::Field)
499*3ac0a46fSAndroid Build Coastguard Worker         return XFA_EventError::kNotExist;
500*3ac0a46fSAndroid Build Coastguard Worker 
501*3ac0a46fSAndroid Build Coastguard Worker       CXFA_Node* pParentNode = GetXFANode()->GetParent();
502*3ac0a46fSAndroid Build Coastguard Worker       if (pParentNode &&
503*3ac0a46fSAndroid Build Coastguard Worker           pParentNode->GetElementType() == XFA_Element::ExclGroup) {
504*3ac0a46fSAndroid Build Coastguard Worker         // TODO(dsinclair): This seems like a bug, we do the same work twice?
505*3ac0a46fSAndroid Build Coastguard Worker         pNotify->ExecEventByDeepFirst(GetXFANode(), eventParaInfo->m_eventType,
506*3ac0a46fSAndroid Build Coastguard Worker                                       false, false);
507*3ac0a46fSAndroid Build Coastguard Worker       }
508*3ac0a46fSAndroid Build Coastguard Worker       return pNotify->ExecEventByDeepFirst(
509*3ac0a46fSAndroid Build Coastguard Worker           GetXFANode(), eventParaInfo->m_eventType, false, false);
510*3ac0a46fSAndroid Build Coastguard Worker     }
511*3ac0a46fSAndroid Build Coastguard Worker     case EventAppliesTo::kField:
512*3ac0a46fSAndroid Build Coastguard Worker       if (eType != XFA_Element::Field)
513*3ac0a46fSAndroid Build Coastguard Worker         return XFA_EventError::kNotExist;
514*3ac0a46fSAndroid Build Coastguard Worker 
515*3ac0a46fSAndroid Build Coastguard Worker       return pNotify->ExecEventByDeepFirst(
516*3ac0a46fSAndroid Build Coastguard Worker           GetXFANode(), eventParaInfo->m_eventType, false, false);
517*3ac0a46fSAndroid Build Coastguard Worker     case EventAppliesTo::kSignature: {
518*3ac0a46fSAndroid Build Coastguard Worker       if (!GetXFANode()->IsWidgetReady())
519*3ac0a46fSAndroid Build Coastguard Worker         return XFA_EventError::kNotExist;
520*3ac0a46fSAndroid Build Coastguard Worker       if (GetXFANode()->GetUIChildNode()->GetElementType() !=
521*3ac0a46fSAndroid Build Coastguard Worker           XFA_Element::Signature) {
522*3ac0a46fSAndroid Build Coastguard Worker         return XFA_EventError::kNotExist;
523*3ac0a46fSAndroid Build Coastguard Worker       }
524*3ac0a46fSAndroid Build Coastguard Worker       return pNotify->ExecEventByDeepFirst(
525*3ac0a46fSAndroid Build Coastguard Worker           GetXFANode(), eventParaInfo->m_eventType, false, false);
526*3ac0a46fSAndroid Build Coastguard Worker     }
527*3ac0a46fSAndroid Build Coastguard Worker     case EventAppliesTo::kChoiceList: {
528*3ac0a46fSAndroid Build Coastguard Worker       if (!GetXFANode()->IsWidgetReady())
529*3ac0a46fSAndroid Build Coastguard Worker         return XFA_EventError::kNotExist;
530*3ac0a46fSAndroid Build Coastguard Worker       if (GetXFANode()->GetUIChildNode()->GetElementType() !=
531*3ac0a46fSAndroid Build Coastguard Worker           XFA_Element::ChoiceList) {
532*3ac0a46fSAndroid Build Coastguard Worker         return XFA_EventError::kNotExist;
533*3ac0a46fSAndroid Build Coastguard Worker       }
534*3ac0a46fSAndroid Build Coastguard Worker       return pNotify->ExecEventByDeepFirst(
535*3ac0a46fSAndroid Build Coastguard Worker           GetXFANode(), eventParaInfo->m_eventType, false, false);
536*3ac0a46fSAndroid Build Coastguard Worker     }
537*3ac0a46fSAndroid Build Coastguard Worker   }
538*3ac0a46fSAndroid Build Coastguard Worker   return XFA_EventError::kNotExist;
539*3ac0a46fSAndroid Build Coastguard Worker }
540