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(
141 GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
142 pCloneNode));
143 }
144
getAttribute(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)145 CJS_Result CJX_Node::getAttribute(
146 CFXJSE_Engine* runtime,
147 const std::vector<v8::Local<v8::Value>>& params) {
148 if (params.size() != 1)
149 return CJS_Result::Failure(JSMessage::kParamError);
150
151 WideString expression = runtime->ToWideString(params[0]);
152 return CJS_Result::Success(runtime->NewString(
153 GetAttributeByString(expression.AsStringView()).ToUTF8().AsStringView()));
154 }
155
getElement(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)156 CJS_Result CJX_Node::getElement(
157 CFXJSE_Engine* runtime,
158 const std::vector<v8::Local<v8::Value>>& params) {
159 if (params.empty() || params.size() > 2)
160 return CJS_Result::Failure(JSMessage::kParamError);
161
162 WideString expression = runtime->ToWideString(params[0]);
163 int32_t iValue = params.size() >= 2 ? runtime->ToInt32(params[1]) : 0;
164 XFA_Element eElement = XFA_GetElementByName(expression.AsStringView());
165 if (eElement == XFA_Element::Unknown)
166 return CJS_Result::Success(runtime->NewNull());
167
168 CXFA_Node* pNode = GetOrCreateProperty<CXFA_Node>(iValue, eElement);
169 if (!pNode)
170 return CJS_Result::Success(runtime->NewNull());
171
172 return CJS_Result::Success(
173 GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pNode));
174 }
175
isPropertySpecified(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)176 CJS_Result CJX_Node::isPropertySpecified(
177 CFXJSE_Engine* runtime,
178 const std::vector<v8::Local<v8::Value>>& params) {
179 if (params.empty() || params.size() > 3)
180 return CJS_Result::Failure(JSMessage::kParamError);
181
182 WideString expression = runtime->ToWideString(params[0]);
183 absl::optional<XFA_ATTRIBUTEINFO> attr =
184 XFA_GetAttributeByName(expression.AsStringView());
185 if (attr.has_value() && HasAttribute(attr.value().attribute))
186 return CJS_Result::Success(runtime->NewBoolean(true));
187
188 XFA_Element eType = XFA_GetElementByName(expression.AsStringView());
189 if (eType == XFA_Element::Unknown)
190 return CJS_Result::Success(runtime->NewBoolean(false));
191
192 bool bParent = params.size() < 2 || runtime->ToBoolean(params[1]);
193 int32_t iIndex = params.size() == 3 ? runtime->ToInt32(params[2]) : 0;
194 bool bHas = !!GetOrCreateProperty<CXFA_Node>(iIndex, eType);
195 if (!bHas && bParent && GetXFANode()->GetParent()) {
196 // Also check on the parent.
197 auto* jsnode = GetXFANode()->GetParent()->JSObject();
198 bHas = jsnode->HasAttribute(attr.value().attribute) ||
199 !!jsnode->GetOrCreateProperty<CXFA_Node>(iIndex, eType);
200 }
201 return CJS_Result::Success(runtime->NewBoolean(bHas));
202 }
203
loadXML(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)204 CJS_Result CJX_Node::loadXML(CFXJSE_Engine* runtime,
205 const std::vector<v8::Local<v8::Value>>& params) {
206 if (params.empty() || params.size() > 3)
207 return CJS_Result::Failure(JSMessage::kParamError);
208
209 ByteString expression = runtime->ToByteString(params[0]);
210 if (expression.IsEmpty())
211 return CJS_Result::Success();
212
213 bool bIgnoreRoot = true;
214 if (params.size() >= 2)
215 bIgnoreRoot = runtime->ToBoolean(params[1]);
216
217 bool bOverwrite = false;
218 if (params.size() >= 3)
219 bOverwrite = runtime->ToBoolean(params[2]);
220
221 auto stream =
222 pdfium::MakeRetain<CFX_ReadOnlyStringStream>(std::move(expression));
223
224 CFX_XMLParser parser(stream);
225 std::unique_ptr<CFX_XMLDocument> xml_doc = parser.Parse();
226 CXFA_DocumentBuilder builder(GetDocument());
227 CFX_XMLNode* pXMLNode = builder.Build(xml_doc.get());
228 if (!pXMLNode)
229 return CJS_Result::Success();
230
231 CFX_XMLDocument* top_xml_doc =
232 GetXFANode()->GetDocument()->GetNotify()->GetFFDoc()->GetXMLDocument();
233 top_xml_doc->AppendNodesFrom(xml_doc.get());
234
235 if (bIgnoreRoot &&
236 (pXMLNode->GetType() != CFX_XMLNode::Type::kElement ||
237 XFA_RecognizeRichText(static_cast<CFX_XMLElement*>(pXMLNode)))) {
238 bIgnoreRoot = false;
239 }
240
241 CXFA_Node* pFakeRoot = GetXFANode()->Clone(false);
242 WideString wsContentType = GetCData(XFA_Attribute::ContentType);
243 if (!wsContentType.IsEmpty()) {
244 pFakeRoot->JSObject()->SetCData(XFA_Attribute::ContentType,
245 WideString(wsContentType));
246 }
247
248 CFX_XMLNode* pFakeXMLRoot = pFakeRoot->GetXMLMappingNode();
249 if (!pFakeXMLRoot) {
250 CFX_XMLNode* pThisXMLRoot = GetXFANode()->GetXMLMappingNode();
251 CFX_XMLNode* clone;
252 if (pThisXMLRoot) {
253 clone = pThisXMLRoot->Clone(top_xml_doc);
254 } else {
255 clone = top_xml_doc->CreateNode<CFX_XMLElement>(
256 WideString::FromASCII(GetXFANode()->GetClassName()));
257 }
258 pFakeXMLRoot = clone;
259 }
260
261 if (bIgnoreRoot) {
262 CFX_XMLNode* pXMLChild = pXMLNode->GetFirstChild();
263 while (pXMLChild) {
264 CFX_XMLNode* pXMLSibling = pXMLChild->GetNextSibling();
265 pXMLNode->RemoveChild(pXMLChild);
266 pFakeXMLRoot->AppendLastChild(pXMLChild);
267 pXMLChild = pXMLSibling;
268 }
269 } else {
270 pXMLNode->RemoveSelfIfParented();
271 pFakeXMLRoot->AppendLastChild(pXMLNode);
272 }
273
274 builder.ConstructXFANode(pFakeRoot, pFakeXMLRoot);
275 pFakeRoot = builder.GetRootNode();
276 if (!pFakeRoot)
277 return CJS_Result::Success();
278
279 if (bOverwrite) {
280 CXFA_Node* pChild = GetXFANode()->GetFirstChild();
281 CXFA_Node* pNewChild = pFakeRoot->GetFirstChild();
282 int32_t index = 0;
283 while (pNewChild) {
284 CXFA_Node* pItem = pNewChild->GetNextSibling();
285 pFakeRoot->RemoveChildAndNotify(pNewChild, true);
286 GetXFANode()->InsertChildAndNotify(index++, pNewChild);
287 pNewChild->SetInitializedFlagAndNotify();
288 pNewChild = pItem;
289 }
290
291 while (pChild) {
292 CXFA_Node* pItem = pChild->GetNextSibling();
293 GetXFANode()->RemoveChildAndNotify(pChild, true);
294 pFakeRoot->InsertChildAndNotify(pChild, nullptr);
295 pChild = pItem;
296 }
297
298 if (GetXFANode()->GetPacketType() == XFA_PacketType::Form &&
299 GetXFANode()->GetElementType() == XFA_Element::ExData) {
300 CFX_XMLNode* pTempXMLNode = GetXFANode()->GetXMLMappingNode();
301 GetXFANode()->SetXMLMappingNode(pFakeXMLRoot);
302
303 if (pTempXMLNode && !pTempXMLNode->GetParent())
304 pFakeXMLRoot = pTempXMLNode;
305 else
306 pFakeXMLRoot = nullptr;
307 }
308 MoveBufferMapData(pFakeRoot, GetXFANode());
309 } else {
310 CXFA_Node* pChild = pFakeRoot->GetFirstChild();
311 while (pChild) {
312 CXFA_Node* pItem = pChild->GetNextSibling();
313 pFakeRoot->RemoveChildAndNotify(pChild, true);
314 GetXFANode()->InsertChildAndNotify(pChild, nullptr);
315 pChild->SetInitializedFlagAndNotify();
316 pChild = pItem;
317 }
318 }
319
320 if (pFakeXMLRoot) {
321 pFakeRoot->SetXMLMappingNode(std::move(pFakeXMLRoot));
322 }
323 pFakeRoot->SetFlag(XFA_NodeFlag::kHasRemovedChildren);
324
325 return CJS_Result::Success();
326 }
327
saveFilteredXML(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)328 CJS_Result CJX_Node::saveFilteredXML(
329 CFXJSE_Engine* runtime,
330 const std::vector<v8::Local<v8::Value>>& params) {
331 // TODO(weili): Check whether we need to implement this, pdfium:501.
332 return CJS_Result::Success();
333 }
334
saveXML(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)335 CJS_Result CJX_Node::saveXML(CFXJSE_Engine* runtime,
336 const std::vector<v8::Local<v8::Value>>& params) {
337 if (params.size() > 1)
338 return CJS_Result::Failure(JSMessage::kParamError);
339
340 if (params.size() == 1 &&
341 !runtime->ToWideString(params[0]).EqualsASCII("pretty")) {
342 return CJS_Result::Failure(JSMessage::kValueError);
343 }
344
345 // TODO(weili): Check whether we need to save pretty print XML, pdfium:501.
346
347 ByteString bsXMLHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
348 if (GetXFANode()->GetPacketType() != XFA_PacketType::Form &&
349 GetXFANode()->GetPacketType() != XFA_PacketType::Datasets) {
350 return CJS_Result::Success(runtime->NewString(""));
351 }
352
353 CFX_XMLNode* pElement = nullptr;
354 if (GetXFANode()->GetPacketType() == XFA_PacketType::Datasets) {
355 pElement = GetXFANode()->GetXMLMappingNode();
356 if (!pElement || pElement->GetType() != CFX_XMLNode::Type::kElement) {
357 return CJS_Result::Success(
358 runtime->NewString(bsXMLHeader.AsStringView()));
359 }
360
361 XFA_DataExporter_DealWithDataGroupNode(GetXFANode());
362 }
363
364 auto pMemoryStream = pdfium::MakeRetain<CFX_MemoryStream>();
365 pMemoryStream->WriteString(bsXMLHeader.AsStringView());
366
367 if (GetXFANode()->GetPacketType() == XFA_PacketType::Form) {
368 XFA_DataExporter_RegenerateFormFile(GetXFANode(), pMemoryStream, true);
369 } else {
370 pElement->Save(pMemoryStream);
371 }
372
373 return CJS_Result::Success(
374 runtime->NewString(ByteStringView(pMemoryStream->GetSpan())));
375 }
376
setAttribute(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)377 CJS_Result CJX_Node::setAttribute(
378 CFXJSE_Engine* runtime,
379 const std::vector<v8::Local<v8::Value>>& params) {
380 if (params.size() != 2)
381 return CJS_Result::Failure(JSMessage::kParamError);
382
383 // Note: yes, arglist is spec'd absolutely backwards from what any sane
384 // person would do, namely value first, attribute second.
385 WideString attributeValue = runtime->ToWideString(params[0]);
386 WideString attribute = runtime->ToWideString(params[1]);
387
388 // Pass them to our method, however, in the more usual manner.
389 SetAttributeByString(attribute.AsStringView(), attributeValue);
390 return CJS_Result::Success();
391 }
392
setElement(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)393 CJS_Result CJX_Node::setElement(
394 CFXJSE_Engine* runtime,
395 const std::vector<v8::Local<v8::Value>>& params) {
396 if (params.size() != 1 && params.size() != 2)
397 return CJS_Result::Failure(JSMessage::kParamError);
398
399 // TODO(weili): check whether we need to implement this, pdfium:501.
400 return CJS_Result::Success();
401 }
402
ns(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)403 void CJX_Node::ns(v8::Isolate* pIsolate,
404 v8::Local<v8::Value>* pValue,
405 bool bSetting,
406 XFA_Attribute eAttribute) {
407 if (bSetting) {
408 ThrowInvalidPropertyException(pIsolate);
409 return;
410 }
411 *pValue = fxv8::NewStringHelper(
412 pIsolate, TryNamespace().value_or(WideString()).ToUTF8().AsStringView());
413 }
414
model(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)415 void CJX_Node::model(v8::Isolate* pIsolate,
416 v8::Local<v8::Value>* pValue,
417 bool bSetting,
418 XFA_Attribute eAttribute) {
419 if (bSetting) {
420 ThrowInvalidPropertyException(pIsolate);
421 return;
422 }
423 CXFA_Node* pModel = GetXFANode()->GetModelNode();
424 if (!pModel) {
425 *pValue = fxv8::NewNullHelper(pIsolate);
426 return;
427 }
428 *pValue =
429 GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pModel);
430 }
431
isContainer(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)432 void CJX_Node::isContainer(v8::Isolate* pIsolate,
433 v8::Local<v8::Value>* pValue,
434 bool bSetting,
435 XFA_Attribute eAttribute) {
436 if (bSetting) {
437 ThrowInvalidPropertyException(pIsolate);
438 return;
439 }
440 *pValue = fxv8::NewBooleanHelper(pIsolate, GetXFANode()->IsContainerNode());
441 }
442
isNull(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)443 void CJX_Node::isNull(v8::Isolate* pIsolate,
444 v8::Local<v8::Value>* pValue,
445 bool bSetting,
446 XFA_Attribute eAttribute) {
447 if (bSetting) {
448 ThrowInvalidPropertyException(pIsolate);
449 return;
450 }
451 if (GetXFANode()->GetElementType() == XFA_Element::Subform) {
452 *pValue = fxv8::NewBooleanHelper(pIsolate, false);
453 return;
454 }
455 *pValue = fxv8::NewBooleanHelper(pIsolate, GetContent(false).IsEmpty());
456 }
457
oneOfChild(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)458 void CJX_Node::oneOfChild(v8::Isolate* pIsolate,
459 v8::Local<v8::Value>* pValue,
460 bool bSetting,
461 XFA_Attribute eAttribute) {
462 if (bSetting) {
463 ThrowInvalidPropertyException(pIsolate);
464 return;
465 }
466
467 std::vector<CXFA_Node*> properties =
468 GetXFANode()->GetNodeListWithFilter(XFA_NodeFilter::kOneOfProperty);
469 if (!properties.empty()) {
470 *pValue = GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
471 properties.front());
472 }
473 }
474
execSingleEventByName(WideStringView wsEventName,XFA_Element eType)475 XFA_EventError CJX_Node::execSingleEventByName(WideStringView wsEventName,
476 XFA_Element eType) {
477 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
478 if (!pNotify)
479 return XFA_EventError::kNotExist;
480
481 const ExecEventParaInfo* eventParaInfo =
482 GetExecEventParaInfoByName(wsEventName);
483 if (!eventParaInfo)
484 return XFA_EventError::kNotExist;
485
486 switch (eventParaInfo->m_validFlags) {
487 case EventAppliesTo::kNone:
488 return XFA_EventError::kNotExist;
489 case EventAppliesTo::kAll:
490 case EventAppliesTo::kAllNonRecursive:
491 return pNotify->ExecEventByDeepFirst(
492 GetXFANode(), eventParaInfo->m_eventType, false,
493 eventParaInfo->m_validFlags == EventAppliesTo::kAll);
494 case EventAppliesTo::kSubform:
495 if (eType != XFA_Element::Subform)
496 return XFA_EventError::kNotExist;
497
498 return pNotify->ExecEventByDeepFirst(
499 GetXFANode(), eventParaInfo->m_eventType, false, false);
500 case EventAppliesTo::kFieldOrExclusion: {
501 if (eType != XFA_Element::ExclGroup && eType != XFA_Element::Field)
502 return XFA_EventError::kNotExist;
503
504 CXFA_Node* pParentNode = GetXFANode()->GetParent();
505 if (pParentNode &&
506 pParentNode->GetElementType() == XFA_Element::ExclGroup) {
507 // TODO(dsinclair): This seems like a bug, we do the same work twice?
508 pNotify->ExecEventByDeepFirst(GetXFANode(), eventParaInfo->m_eventType,
509 false, false);
510 }
511 return pNotify->ExecEventByDeepFirst(
512 GetXFANode(), eventParaInfo->m_eventType, false, false);
513 }
514 case EventAppliesTo::kField:
515 if (eType != XFA_Element::Field)
516 return XFA_EventError::kNotExist;
517
518 return pNotify->ExecEventByDeepFirst(
519 GetXFANode(), eventParaInfo->m_eventType, false, false);
520 case EventAppliesTo::kSignature: {
521 if (!GetXFANode()->IsWidgetReady())
522 return XFA_EventError::kNotExist;
523 if (GetXFANode()->GetUIChildNode()->GetElementType() !=
524 XFA_Element::Signature) {
525 return XFA_EventError::kNotExist;
526 }
527 return pNotify->ExecEventByDeepFirst(
528 GetXFANode(), eventParaInfo->m_eventType, false, false);
529 }
530 case EventAppliesTo::kChoiceList: {
531 if (!GetXFANode()->IsWidgetReady())
532 return XFA_EventError::kNotExist;
533 if (GetXFANode()->GetUIChildNode()->GetElementType() !=
534 XFA_Element::ChoiceList) {
535 return XFA_EventError::kNotExist;
536 }
537 return pNotify->ExecEventByDeepFirst(
538 GetXFANode(), eventParaInfo->m_eventType, false, false);
539 }
540 }
541 return XFA_EventError::kNotExist;
542 }
543