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