• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <vector>
11 
12 #include "core/fxcrt/cfx_memorystream.h"
13 #include "core/fxcrt/fx_codepage.h"
14 #include "fxjs/cfxjse_engine.h"
15 #include "fxjs/js_resources.h"
16 #include "third_party/base/ptr_util.h"
17 #include "xfa/fxfa/cxfa_eventparam.h"
18 #include "xfa/fxfa/cxfa_ffnotify.h"
19 #include "xfa/fxfa/parser/cxfa_document.h"
20 #include "xfa/fxfa/parser/cxfa_node.h"
21 #include "xfa/fxfa/parser/cxfa_simple_parser.h"
22 #include "xfa/fxfa/parser/xfa_utils.h"
23 
24 namespace {
25 
26 enum class EventAppliesToo {
27   kNone = 0,
28   kAll = 1,
29   kAllNonRecursive = 2,
30   kSubform = 3,
31   kFieldOrExclusion = 4,
32   kField = 5,
33   kSignature = 6,
34   kChoiceList = 7
35 };
36 
37 struct XFA_ExecEventParaInfo {
38  public:
39   uint32_t m_uHash;
40   const wchar_t* m_lpcEventName;
41   XFA_EVENTTYPE m_eventType;
42   EventAppliesToo m_validFlags;
43 };
44 
45 const XFA_ExecEventParaInfo gs_eventParaInfos[] = {
46     {0x109d7ce7, L"mouseEnter", XFA_EVENT_MouseEnter, EventAppliesToo::kField},
47     {0x1bfc72d9, L"preOpen", XFA_EVENT_PreOpen, EventAppliesToo::kChoiceList},
48     {0x2196a452, L"initialize", XFA_EVENT_Initialize, EventAppliesToo::kAll},
49     {0x27410f03, L"mouseExit", XFA_EVENT_MouseExit, EventAppliesToo::kField},
50     {0x36f1c6d8, L"preSign", XFA_EVENT_PreSign, EventAppliesToo::kSignature},
51     {0x4731d6ba, L"exit", XFA_EVENT_Exit, EventAppliesToo::kAllNonRecursive},
52     {0x7233018a, L"validate", XFA_EVENT_Validate, EventAppliesToo::kAll},
53     {0x8808385e, L"indexChange", XFA_EVENT_IndexChange,
54      EventAppliesToo::kSubform},
55     {0x891f4606, L"change", XFA_EVENT_Change,
56      EventAppliesToo::kFieldOrExclusion},
57     {0x9f693b21, L"mouseDown", XFA_EVENT_MouseDown, EventAppliesToo::kField},
58     {0xcdce56b3, L"full", XFA_EVENT_Full, EventAppliesToo::kFieldOrExclusion},
59     {0xd576d08e, L"mouseUp", XFA_EVENT_MouseUp, EventAppliesToo::kField},
60     {0xd95657a6, L"click", XFA_EVENT_Click, EventAppliesToo::kFieldOrExclusion},
61     {0xdbfbe02e, L"calculate", XFA_EVENT_Calculate, EventAppliesToo::kAll},
62     {0xe25fa7b8, L"postOpen", XFA_EVENT_PostOpen, EventAppliesToo::kChoiceList},
63     {0xe28dce7e, L"enter", XFA_EVENT_Enter, EventAppliesToo::kAllNonRecursive},
64     {0xfd54fbb7, L"postSign", XFA_EVENT_PostSign, EventAppliesToo::kSignature},
65 };
66 
GetEventParaInfoByName(const WideStringView & wsEventName)67 const XFA_ExecEventParaInfo* GetEventParaInfoByName(
68     const WideStringView& wsEventName) {
69   uint32_t uHash = FX_HashCode_GetW(wsEventName, false);
70   int32_t iStart = 0;
71   int32_t iEnd = (sizeof(gs_eventParaInfos) / sizeof(gs_eventParaInfos[0])) - 1;
72   do {
73     int32_t iMid = (iStart + iEnd) / 2;
74     const XFA_ExecEventParaInfo* eventParaInfo = &gs_eventParaInfos[iMid];
75     if (uHash == eventParaInfo->m_uHash)
76       return eventParaInfo;
77     if (uHash < eventParaInfo->m_uHash)
78       iEnd = iMid - 1;
79     else
80       iStart = iMid + 1;
81   } while (iStart <= iEnd);
82   return nullptr;
83 }
84 
85 }  // namespace
86 
87 const CJX_MethodSpec CJX_Node::MethodSpecs[] = {
88     {"applyXSL", applyXSL_static},
89     {"assignNode", assignNode_static},
90     {"clone", clone_static},
91     {"getAttribute", getAttribute_static},
92     {"getElement", getElement_static},
93     {"isPropertySpecified", isPropertySpecified_static},
94     {"loadXML", loadXML_static},
95     {"saveFilteredXML", saveFilteredXML_static},
96     {"saveXML", saveXML_static},
97     {"setAttribute", setAttribute_static},
98     {"setElement", setElement_static}};
99 
CJX_Node(CXFA_Node * node)100 CJX_Node::CJX_Node(CXFA_Node* node) : CJX_Tree(node) {
101   DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs));
102 }
103 
104 CJX_Node::~CJX_Node() = default;
105 
GetXFANode()106 CXFA_Node* CJX_Node::GetXFANode() {
107   return static_cast<CXFA_Node*>(GetXFAObject());
108 }
109 
GetXFANode() const110 const CXFA_Node* CJX_Node::GetXFANode() const {
111   return static_cast<const CXFA_Node*>(GetXFAObject());
112 }
113 
applyXSL(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)114 CJS_Return CJX_Node::applyXSL(CJS_V8* runtime,
115                               const std::vector<v8::Local<v8::Value>>& params) {
116   if (params.size() != 1)
117     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
118 
119   // TODO(weili): check whether we need to implement this, pdfium:501.
120   return CJS_Return(true);
121 }
122 
assignNode(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)123 CJS_Return CJX_Node::assignNode(
124     CJS_V8* runtime,
125     const std::vector<v8::Local<v8::Value>>& params) {
126   if (params.empty() || params.size() > 3)
127     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
128 
129   // TODO(weili): check whether we need to implement this, pdfium:501.
130   return CJS_Return(true);
131 }
132 
clone(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)133 CJS_Return CJX_Node::clone(CJS_V8* runtime,
134                            const std::vector<v8::Local<v8::Value>>& params) {
135   if (params.size() != 1)
136     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
137 
138   CXFA_Node* pCloneNode = GetXFANode()->Clone(runtime->ToBoolean(params[0]));
139   CFXJSE_Value* value =
140       GetDocument()->GetScriptContext()->GetJSValueFromMap(pCloneNode);
141   if (!value)
142     return CJS_Return(runtime->NewNull());
143   return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate()));
144 }
145 
getAttribute(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)146 CJS_Return CJX_Node::getAttribute(
147     CJS_V8* runtime,
148     const std::vector<v8::Local<v8::Value>>& params) {
149   if (params.size() != 1)
150     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
151 
152   WideString expression = runtime->ToWideString(params[0]);
153   return CJS_Return(runtime->NewString(
154       GetAttribute(expression.AsStringView()).UTF8Encode().AsStringView()));
155 }
156 
getElement(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)157 CJS_Return CJX_Node::getElement(
158     CJS_V8* runtime,
159     const std::vector<v8::Local<v8::Value>>& params) {
160   if (params.empty() || params.size() > 2)
161     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
162 
163   WideString expression = runtime->ToWideString(params[0]);
164   int32_t iValue = params.size() >= 2 ? runtime->ToInt32(params[1]) : 0;
165 
166   CXFA_Node* pNode = GetOrCreateProperty<CXFA_Node>(
167       iValue, CXFA_Node::NameToElement(expression));
168   if (!pNode)
169     return CJS_Return(runtime->NewNull());
170 
171   CFXJSE_Value* value =
172       GetDocument()->GetScriptContext()->GetJSValueFromMap(pNode);
173   if (!value)
174     return CJS_Return(runtime->NewNull());
175   return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate()));
176 }
177 
isPropertySpecified(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)178 CJS_Return CJX_Node::isPropertySpecified(
179     CJS_V8* runtime,
180     const std::vector<v8::Local<v8::Value>>& params) {
181   if (params.empty() || params.size() > 3)
182     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
183 
184   WideString expression = runtime->ToWideString(params[0]);
185   XFA_Attribute attr = CXFA_Node::NameToAttribute(expression.AsStringView());
186   if (attr != XFA_Attribute::Unknown && HasAttribute(attr))
187     return CJS_Return(runtime->NewBoolean(true));
188 
189   bool bParent = params.size() < 2 || runtime->ToBoolean(params[1]);
190   int32_t iIndex = params.size() == 3 ? runtime->ToInt32(params[2]) : 0;
191   XFA_Element eType = CXFA_Node::NameToElement(expression);
192   bool bHas = !!GetOrCreateProperty<CXFA_Node>(iIndex, eType);
193   if (!bHas && bParent && GetXFANode()->GetParent()) {
194     // Also check on the parent.
195     auto* jsnode = GetXFANode()->GetParent()->JSObject();
196     bHas = jsnode->HasAttribute(attr) ||
197            !!jsnode->GetOrCreateProperty<CXFA_Node>(iIndex, eType);
198   }
199   return CJS_Return(runtime->NewBoolean(bHas));
200 }
201 
loadXML(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)202 CJS_Return CJX_Node::loadXML(CJS_V8* runtime,
203                              const std::vector<v8::Local<v8::Value>>& params) {
204   if (params.empty() || params.size() > 3)
205     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
206 
207   ByteString expression = runtime->ToByteString(params[0]);
208   if (expression.IsEmpty())
209     return CJS_Return(true);
210 
211   bool bIgnoreRoot = true;
212   if (params.size() >= 2)
213     bIgnoreRoot = runtime->ToBoolean(params[1]);
214 
215   bool bOverwrite = 0;
216   if (params.size() >= 3)
217     bOverwrite = runtime->ToBoolean(params[2]);
218 
219   auto pParser = pdfium::MakeUnique<CXFA_SimpleParser>(GetDocument());
220   if (!pParser)
221     return CJS_Return(true);
222 
223   CFX_XMLNode* pXMLNode = pParser->ParseXMLData(expression);
224   if (!pXMLNode)
225     return CJS_Return(true);
226 
227   if (bIgnoreRoot &&
228       (pXMLNode->GetType() != FX_XMLNODE_Element ||
229        XFA_RecognizeRichText(static_cast<CFX_XMLElement*>(pXMLNode)))) {
230     bIgnoreRoot = false;
231   }
232 
233   CXFA_Node* pFakeRoot = GetXFANode()->Clone(false);
234   WideString wsContentType = GetCData(XFA_Attribute::ContentType);
235   if (!wsContentType.IsEmpty()) {
236     pFakeRoot->JSObject()->SetCData(XFA_Attribute::ContentType,
237                                     WideString(wsContentType), false, false);
238   }
239 
240   std::unique_ptr<CFX_XMLNode> pFakeXMLRoot(pFakeRoot->GetXMLMappingNode());
241   if (!pFakeXMLRoot) {
242     CFX_XMLNode* pThisXMLRoot = GetXFANode()->GetXMLMappingNode();
243     pFakeXMLRoot = pThisXMLRoot ? pThisXMLRoot->Clone() : nullptr;
244   }
245   if (!pFakeXMLRoot) {
246     pFakeXMLRoot = pdfium::MakeUnique<CFX_XMLElement>(
247         WideString(GetXFANode()->GetClassName()));
248   }
249 
250   if (bIgnoreRoot) {
251     CFX_XMLNode* pXMLChild = pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild);
252     while (pXMLChild) {
253       CFX_XMLNode* pXMLSibling =
254           pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling);
255       pXMLNode->RemoveChildNode(pXMLChild);
256       pFakeXMLRoot->InsertChildNode(pXMLChild);
257       pXMLChild = pXMLSibling;
258     }
259   } else {
260     CFX_XMLNode* pXMLParent = pXMLNode->GetNodeItem(CFX_XMLNode::Parent);
261     if (pXMLParent)
262       pXMLParent->RemoveChildNode(pXMLNode);
263 
264     pFakeXMLRoot->InsertChildNode(pXMLNode);
265   }
266 
267   pParser->ConstructXFANode(pFakeRoot, pFakeXMLRoot.get());
268   pFakeRoot = pParser->GetRootNode();
269   if (!pFakeRoot)
270     return CJS_Return(true);
271 
272   if (bOverwrite) {
273     CXFA_Node* pChild = GetXFANode()->GetFirstChild();
274     CXFA_Node* pNewChild = pFakeRoot->GetFirstChild();
275     int32_t index = 0;
276     while (pNewChild) {
277       CXFA_Node* pItem = pNewChild->GetNextSibling();
278       pFakeRoot->RemoveChild(pNewChild, true);
279       GetXFANode()->InsertChild(index++, pNewChild);
280       pNewChild->SetFlag(XFA_NodeFlag_Initialized, true);
281       pNewChild = pItem;
282     }
283 
284     while (pChild) {
285       CXFA_Node* pItem = pChild->GetNextSibling();
286       GetXFANode()->RemoveChild(pChild, true);
287       pFakeRoot->InsertChild(pChild, nullptr);
288       pChild = pItem;
289     }
290 
291     if (GetXFANode()->GetPacketType() == XFA_PacketType::Form &&
292         GetXFANode()->GetElementType() == XFA_Element::ExData) {
293       CFX_XMLNode* pTempXMLNode = GetXFANode()->GetXMLMappingNode();
294       GetXFANode()->SetXMLMappingNode(pFakeXMLRoot.release());
295       GetXFANode()->SetFlag(XFA_NodeFlag_OwnXMLNode, false);
296       if (pTempXMLNode && !pTempXMLNode->GetNodeItem(CFX_XMLNode::Parent))
297         pFakeXMLRoot.reset(pTempXMLNode);
298       else
299         pFakeXMLRoot = nullptr;
300     }
301     MoveBufferMapData(pFakeRoot, GetXFANode());
302   } else {
303     CXFA_Node* pChild = pFakeRoot->GetFirstChild();
304     while (pChild) {
305       CXFA_Node* pItem = pChild->GetNextSibling();
306       pFakeRoot->RemoveChild(pChild, true);
307       GetXFANode()->InsertChild(pChild, nullptr);
308       pChild->SetFlag(XFA_NodeFlag_Initialized, true);
309       pChild = pItem;
310     }
311   }
312 
313   if (pFakeXMLRoot) {
314     pFakeRoot->SetXMLMappingNode(pFakeXMLRoot.release());
315     pFakeRoot->SetFlag(XFA_NodeFlag_OwnXMLNode, false);
316   }
317   pFakeRoot->SetFlag(XFA_NodeFlag_HasRemovedChildren, false);
318 
319   return CJS_Return(true);
320 }
321 
saveFilteredXML(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)322 CJS_Return CJX_Node::saveFilteredXML(
323     CJS_V8* runtime,
324     const std::vector<v8::Local<v8::Value>>& params) {
325   // TODO(weili): Check whether we need to implement this, pdfium:501.
326   return CJS_Return(true);
327 }
328 
saveXML(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)329 CJS_Return CJX_Node::saveXML(CJS_V8* runtime,
330                              const std::vector<v8::Local<v8::Value>>& params) {
331   if (params.size() > 1)
332     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
333   if (params.size() == 1 && runtime->ToWideString(params[0]) != L"pretty")
334     return CJS_Return(JSGetStringFromID(JSMessage::kValueError));
335 
336   // TODO(weili): Check whether we need to save pretty print XML, pdfium:501.
337 
338   WideString bsXMLHeader = L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
339   if (GetXFANode()->GetPacketType() != XFA_PacketType::Form &&
340       GetXFANode()->GetPacketType() != XFA_PacketType::Datasets) {
341     return CJS_Return(runtime->NewString(""));
342   }
343 
344   CFX_XMLNode* pElement = nullptr;
345   if (GetXFANode()->GetPacketType() == XFA_PacketType::Datasets) {
346     pElement = GetXFANode()->GetXMLMappingNode();
347     if (!pElement || pElement->GetType() != FX_XMLNODE_Element) {
348       return CJS_Return(
349           runtime->NewString(bsXMLHeader.UTF8Encode().AsStringView()));
350     }
351 
352     XFA_DataExporter_DealWithDataGroupNode(GetXFANode());
353   }
354 
355   auto pMemoryStream = pdfium::MakeRetain<CFX_MemoryStream>(true);
356   auto pStream =
357       pdfium::MakeRetain<CFX_SeekableStreamProxy>(pMemoryStream, true);
358   pStream->SetCodePage(FX_CODEPAGE_UTF8);
359   pStream->WriteString(bsXMLHeader.AsStringView());
360 
361   if (GetXFANode()->GetPacketType() == XFA_PacketType::Form)
362     XFA_DataExporter_RegenerateFormFile(GetXFANode(), pStream, nullptr, true);
363   else
364     pElement->SaveXMLNode(pStream);
365 
366   return CJS_Return(runtime->NewString(
367       ByteStringView(pMemoryStream->GetBuffer(), pMemoryStream->GetSize())));
368 }
369 
setAttribute(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)370 CJS_Return CJX_Node::setAttribute(
371     CJS_V8* runtime,
372     const std::vector<v8::Local<v8::Value>>& params) {
373   if (params.size() != 2)
374     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
375 
376   WideString attributeValue = runtime->ToWideString(params[0]);
377   WideString attribute = runtime->ToWideString(params[1]);
378   SetAttribute(attribute.AsStringView(), attributeValue.AsStringView(), true);
379   return CJS_Return(true);
380 }
381 
setElement(CJS_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)382 CJS_Return CJX_Node::setElement(
383     CJS_V8* runtime,
384     const std::vector<v8::Local<v8::Value>>& params) {
385   if (params.size() != 1 && params.size() != 2)
386     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
387 
388   // TODO(weili): check whether we need to implement this, pdfium:501.
389   return CJS_Return(true);
390 }
391 
id(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)392 void CJX_Node::id(CFXJSE_Value* pValue,
393                   bool bSetting,
394                   XFA_Attribute eAttribute) {
395   Script_Attribute_String(pValue, bSetting, eAttribute);
396 }
397 
ns(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)398 void CJX_Node::ns(CFXJSE_Value* pValue,
399                   bool bSetting,
400                   XFA_Attribute eAttribute) {
401   if (bSetting) {
402     ThrowInvalidPropertyException();
403     return;
404   }
405   pValue->SetString(
406       TryNamespace().value_or(WideString()).UTF8Encode().AsStringView());
407 }
408 
model(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)409 void CJX_Node::model(CFXJSE_Value* pValue,
410                      bool bSetting,
411                      XFA_Attribute eAttribute) {
412   if (bSetting) {
413     ThrowInvalidPropertyException();
414     return;
415   }
416   pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(
417       GetXFANode()->GetModelNode()));
418 }
419 
isContainer(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)420 void CJX_Node::isContainer(CFXJSE_Value* pValue,
421                            bool bSetting,
422                            XFA_Attribute eAttribute) {
423   if (bSetting) {
424     ThrowInvalidPropertyException();
425     return;
426   }
427   pValue->SetBoolean(GetXFANode()->IsContainerNode());
428 }
429 
isNull(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)430 void CJX_Node::isNull(CFXJSE_Value* pValue,
431                       bool bSetting,
432                       XFA_Attribute eAttribute) {
433   if (bSetting) {
434     ThrowInvalidPropertyException();
435     return;
436   }
437   if (GetXFANode()->GetElementType() == XFA_Element::Subform) {
438     pValue->SetBoolean(false);
439     return;
440   }
441   pValue->SetBoolean(GetContent(false).IsEmpty());
442 }
443 
oneOfChild(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)444 void CJX_Node::oneOfChild(CFXJSE_Value* pValue,
445                           bool bSetting,
446                           XFA_Attribute eAttribute) {
447   if (bSetting) {
448     ThrowInvalidPropertyException();
449     return;
450   }
451 
452   std::vector<CXFA_Node*> properties = GetXFANode()->GetNodeList(
453       XFA_NODEFILTER_OneOfProperty, XFA_Element::Unknown);
454   if (!properties.empty()) {
455     pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(
456         properties.front()));
457   }
458 }
459 
execSingleEventByName(const WideStringView & wsEventName,XFA_Element eType)460 int32_t CJX_Node::execSingleEventByName(const WideStringView& wsEventName,
461                                         XFA_Element eType) {
462   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
463   if (!pNotify)
464     return XFA_EVENTERROR_NotExist;
465 
466   const XFA_ExecEventParaInfo* eventParaInfo =
467       GetEventParaInfoByName(wsEventName);
468   if (!eventParaInfo)
469     return XFA_EVENTERROR_NotExist;
470 
471   switch (eventParaInfo->m_validFlags) {
472     case EventAppliesToo::kNone:
473       return XFA_EVENTERROR_NotExist;
474     case EventAppliesToo::kAll:
475     case EventAppliesToo::kAllNonRecursive:
476       return pNotify->ExecEventByDeepFirst(
477           GetXFANode(), eventParaInfo->m_eventType, false,
478           eventParaInfo->m_validFlags == EventAppliesToo::kAll);
479     case EventAppliesToo::kSubform:
480       if (eType != XFA_Element::Subform)
481         return XFA_EVENTERROR_NotExist;
482 
483       return pNotify->ExecEventByDeepFirst(
484           GetXFANode(), eventParaInfo->m_eventType, false, false);
485     case EventAppliesToo::kFieldOrExclusion: {
486       if (eType != XFA_Element::ExclGroup && eType != XFA_Element::Field)
487         return XFA_EVENTERROR_NotExist;
488 
489       CXFA_Node* pParentNode = GetXFANode()->GetParent();
490       if (pParentNode &&
491           pParentNode->GetElementType() == XFA_Element::ExclGroup) {
492         // TODO(dsinclair): This seems like a bug, we do the same work twice?
493         pNotify->ExecEventByDeepFirst(GetXFANode(), eventParaInfo->m_eventType,
494                                       false, false);
495       }
496       return pNotify->ExecEventByDeepFirst(
497           GetXFANode(), eventParaInfo->m_eventType, false, false);
498     }
499     case EventAppliesToo::kField:
500       if (eType != XFA_Element::Field)
501         return XFA_EVENTERROR_NotExist;
502 
503       return pNotify->ExecEventByDeepFirst(
504           GetXFANode(), eventParaInfo->m_eventType, false, false);
505     case EventAppliesToo::kSignature: {
506       CXFA_WidgetAcc* pWidgetAcc = GetXFANode()->GetWidgetAcc();
507       if (!pWidgetAcc)
508         return XFA_EVENTERROR_NotExist;
509 
510       CXFA_Node* pUINode = pWidgetAcc->GetUIChild();
511       if (pUINode->GetElementType() != XFA_Element::Signature)
512         return XFA_EVENTERROR_NotExist;
513 
514       return pNotify->ExecEventByDeepFirst(
515           GetXFANode(), eventParaInfo->m_eventType, false, false);
516     }
517     case EventAppliesToo::kChoiceList: {
518       CXFA_WidgetAcc* pWidgetAcc = GetXFANode()->GetWidgetAcc();
519       if (!pWidgetAcc)
520         return XFA_EVENTERROR_NotExist;
521 
522       CXFA_Node* pUINode = pWidgetAcc->GetUIChild();
523       if (pUINode->GetElementType() != XFA_Element::ChoiceList ||
524           pWidgetAcc->IsListBox()) {
525         return XFA_EVENTERROR_NotExist;
526       }
527       return pNotify->ExecEventByDeepFirst(
528           GetXFANode(), eventParaInfo->m_eventType, false, false);
529     }
530   }
531   return XFA_EVENTERROR_NotExist;
532 }
533