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