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_eventpseudomodel.h"
8 
9 #include <algorithm>
10 #include <vector>
11 
12 #include "fxjs/xfa/cfxjse_engine.h"
13 #include "fxjs/xfa/cfxjse_value.h"
14 #include "xfa/fxfa/cxfa_eventparam.h"
15 #include "xfa/fxfa/cxfa_ffnotify.h"
16 #include "xfa/fxfa/cxfa_ffwidgethandler.h"
17 #include "xfa/fxfa/parser/cscript_eventpseudomodel.h"
18 
19 namespace {
20 
StringProperty(CFXJSE_Value * pReturn,WideString * wsValue,bool bSetting)21 void StringProperty(CFXJSE_Value* pReturn, WideString* wsValue, bool bSetting) {
22   if (bSetting) {
23     *wsValue = pReturn->ToWideString();
24     return;
25   }
26   pReturn->SetString(wsValue->ToUTF8().AsStringView());
27 }
28 
IntegerProperty(CFXJSE_Value * pReturn,int32_t * iValue,bool bSetting)29 void IntegerProperty(CFXJSE_Value* pReturn, int32_t* iValue, bool bSetting) {
30   if (bSetting) {
31     *iValue = pReturn->ToInteger();
32     return;
33   }
34   pReturn->SetInteger(*iValue);
35 }
36 
BooleanProperty(CFXJSE_Value * pReturn,bool * bValue,bool bSetting)37 void BooleanProperty(CFXJSE_Value* pReturn, bool* bValue, bool bSetting) {
38   if (bSetting) {
39     *bValue = pReturn->ToBoolean();
40     return;
41   }
42   pReturn->SetBoolean(*bValue);
43 }
44 
45 }  // namespace
46 
47 const CJX_MethodSpec CJX_EventPseudoModel::MethodSpecs[] = {
48     {"emit", emit_static},
49     {"reset", reset_static}};
50 
CJX_EventPseudoModel(CScript_EventPseudoModel * model)51 CJX_EventPseudoModel::CJX_EventPseudoModel(CScript_EventPseudoModel* model)
52     : CJX_Object(model) {
53   DefineMethods(MethodSpecs);
54 }
55 
~CJX_EventPseudoModel()56 CJX_EventPseudoModel::~CJX_EventPseudoModel() {}
57 
DynamicTypeIs(TypeTag eType) const58 bool CJX_EventPseudoModel::DynamicTypeIs(TypeTag eType) const {
59   return eType == static_type__ || ParentType__::DynamicTypeIs(eType);
60 }
61 
cancelAction(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)62 void CJX_EventPseudoModel::cancelAction(CFXJSE_Value* pValue,
63                                         bool bSetting,
64                                         XFA_Attribute eAttribute) {
65   Property(pValue, XFA_Event::CancelAction, bSetting);
66 }
67 
change(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)68 void CJX_EventPseudoModel::change(CFXJSE_Value* pValue,
69                                   bool bSetting,
70                                   XFA_Attribute eAttribute) {
71   Property(pValue, XFA_Event::Change, bSetting);
72 }
73 
commitKey(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)74 void CJX_EventPseudoModel::commitKey(CFXJSE_Value* pValue,
75                                      bool bSetting,
76                                      XFA_Attribute eAttribute) {
77   Property(pValue, XFA_Event::CommitKey, bSetting);
78 }
79 
fullText(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)80 void CJX_EventPseudoModel::fullText(CFXJSE_Value* pValue,
81                                     bool bSetting,
82                                     XFA_Attribute eAttribute) {
83   Property(pValue, XFA_Event::FullText, bSetting);
84 }
85 
keyDown(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)86 void CJX_EventPseudoModel::keyDown(CFXJSE_Value* pValue,
87                                    bool bSetting,
88                                    XFA_Attribute eAttribute) {
89   Property(pValue, XFA_Event::Keydown, bSetting);
90 }
91 
modifier(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)92 void CJX_EventPseudoModel::modifier(CFXJSE_Value* pValue,
93                                     bool bSetting,
94                                     XFA_Attribute eAttribute) {
95   Property(pValue, XFA_Event::Modifier, bSetting);
96 }
97 
newContentType(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)98 void CJX_EventPseudoModel::newContentType(CFXJSE_Value* pValue,
99                                           bool bSetting,
100                                           XFA_Attribute eAttribute) {
101   Property(pValue, XFA_Event::NewContentType, bSetting);
102 }
103 
newText(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)104 void CJX_EventPseudoModel::newText(CFXJSE_Value* pValue,
105                                    bool bSetting,
106                                    XFA_Attribute eAttribute) {
107   if (bSetting)
108     return;
109 
110   CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
111   CXFA_EventParam* pEventParam = pScriptContext->GetEventParam();
112   if (!pEventParam)
113     return;
114 
115   pValue->SetString(pEventParam->GetNewText().ToUTF8().AsStringView());
116 }
117 
prevContentType(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)118 void CJX_EventPseudoModel::prevContentType(CFXJSE_Value* pValue,
119                                            bool bSetting,
120                                            XFA_Attribute eAttribute) {
121   Property(pValue, XFA_Event::PreviousContentType, bSetting);
122 }
123 
prevText(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)124 void CJX_EventPseudoModel::prevText(CFXJSE_Value* pValue,
125                                     bool bSetting,
126                                     XFA_Attribute eAttribute) {
127   Property(pValue, XFA_Event::PreviousText, bSetting);
128 }
129 
reenter(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)130 void CJX_EventPseudoModel::reenter(CFXJSE_Value* pValue,
131                                    bool bSetting,
132                                    XFA_Attribute eAttribute) {
133   Property(pValue, XFA_Event::Reenter, bSetting);
134 }
135 
selEnd(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)136 void CJX_EventPseudoModel::selEnd(CFXJSE_Value* pValue,
137                                   bool bSetting,
138                                   XFA_Attribute eAttribute) {
139   Property(pValue, XFA_Event::SelectionEnd, bSetting);
140 }
141 
selStart(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)142 void CJX_EventPseudoModel::selStart(CFXJSE_Value* pValue,
143                                     bool bSetting,
144                                     XFA_Attribute eAttribute) {
145   Property(pValue, XFA_Event::SelectionStart, bSetting);
146 }
147 
shift(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)148 void CJX_EventPseudoModel::shift(CFXJSE_Value* pValue,
149                                  bool bSetting,
150                                  XFA_Attribute eAttribute) {
151   Property(pValue, XFA_Event::Shift, bSetting);
152 }
153 
soapFaultCode(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)154 void CJX_EventPseudoModel::soapFaultCode(CFXJSE_Value* pValue,
155                                          bool bSetting,
156                                          XFA_Attribute eAttribute) {
157   Property(pValue, XFA_Event::SoapFaultCode, bSetting);
158 }
159 
soapFaultString(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)160 void CJX_EventPseudoModel::soapFaultString(CFXJSE_Value* pValue,
161                                            bool bSetting,
162                                            XFA_Attribute eAttribute) {
163   Property(pValue, XFA_Event::SoapFaultString, bSetting);
164 }
165 
target(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)166 void CJX_EventPseudoModel::target(CFXJSE_Value* pValue,
167                                   bool bSetting,
168                                   XFA_Attribute eAttribute) {
169   Property(pValue, XFA_Event::Target, bSetting);
170 }
171 
emit(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)172 CJS_Result CJX_EventPseudoModel::emit(
173     CFX_V8* runtime,
174     const std::vector<v8::Local<v8::Value>>& params) {
175   CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
176   CXFA_EventParam* pEventParam = pScriptContext->GetEventParam();
177   if (!pEventParam)
178     return CJS_Result::Success();
179 
180   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
181   if (!pNotify)
182     return CJS_Result::Success();
183 
184   CXFA_FFWidgetHandler* pWidgetHandler = pNotify->GetWidgetHandler();
185   if (!pWidgetHandler)
186     return CJS_Result::Success();
187 
188   pWidgetHandler->ProcessEvent(pEventParam->m_pTarget.Get(), pEventParam);
189   return CJS_Result::Success();
190 }
191 
reset(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)192 CJS_Result CJX_EventPseudoModel::reset(
193     CFX_V8* runtime,
194     const std::vector<v8::Local<v8::Value>>& params) {
195   CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
196   CXFA_EventParam* pEventParam = pScriptContext->GetEventParam();
197   if (pEventParam)
198     *pEventParam = CXFA_EventParam();
199 
200   return CJS_Result::Success();
201 }
202 
Property(CFXJSE_Value * pValue,XFA_Event dwFlag,bool bSetting)203 void CJX_EventPseudoModel::Property(CFXJSE_Value* pValue,
204                                     XFA_Event dwFlag,
205                                     bool bSetting) {
206   // Only the cancelAction, selStart, selEnd and change properties are writable.
207   if (bSetting && dwFlag != XFA_Event::CancelAction &&
208       dwFlag != XFA_Event::SelectionStart &&
209       dwFlag != XFA_Event::SelectionEnd && dwFlag != XFA_Event::Change) {
210     return;
211   }
212 
213   CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
214   CXFA_EventParam* pEventParam = pScriptContext->GetEventParam();
215   if (!pEventParam)
216     return;
217 
218   switch (dwFlag) {
219     case XFA_Event::CancelAction:
220       BooleanProperty(pValue, &pEventParam->m_bCancelAction, bSetting);
221       break;
222     case XFA_Event::Change:
223       StringProperty(pValue, &pEventParam->m_wsChange, bSetting);
224       break;
225     case XFA_Event::CommitKey:
226       IntegerProperty(pValue, &pEventParam->m_iCommitKey, bSetting);
227       break;
228     case XFA_Event::FullText:
229       StringProperty(pValue, &pEventParam->m_wsFullText, bSetting);
230       break;
231     case XFA_Event::Keydown:
232       BooleanProperty(pValue, &pEventParam->m_bKeyDown, bSetting);
233       break;
234     case XFA_Event::Modifier:
235       BooleanProperty(pValue, &pEventParam->m_bModifier, bSetting);
236       break;
237     case XFA_Event::NewContentType:
238       StringProperty(pValue, &pEventParam->m_wsNewContentType, bSetting);
239       break;
240     case XFA_Event::NewText:
241       NOTREACHED();
242       break;
243     case XFA_Event::PreviousContentType:
244       StringProperty(pValue, &pEventParam->m_wsPrevContentType, bSetting);
245       break;
246     case XFA_Event::PreviousText:
247       StringProperty(pValue, &pEventParam->m_wsPrevText, bSetting);
248       break;
249     case XFA_Event::Reenter:
250       BooleanProperty(pValue, &pEventParam->m_bReenter, bSetting);
251       break;
252     case XFA_Event::SelectionEnd:
253       IntegerProperty(pValue, &pEventParam->m_iSelEnd, bSetting);
254 
255       pEventParam->m_iSelEnd = std::max(0, pEventParam->m_iSelEnd);
256       pEventParam->m_iSelEnd =
257           std::min(static_cast<size_t>(pEventParam->m_iSelEnd),
258                    pEventParam->m_wsPrevText.GetLength());
259       pEventParam->m_iSelStart =
260           std::min(pEventParam->m_iSelStart, pEventParam->m_iSelEnd);
261       break;
262     case XFA_Event::SelectionStart:
263       IntegerProperty(pValue, &pEventParam->m_iSelStart, bSetting);
264       pEventParam->m_iSelStart = std::max(0, pEventParam->m_iSelStart);
265       pEventParam->m_iSelStart =
266           std::min(static_cast<size_t>(pEventParam->m_iSelStart),
267                    pEventParam->m_wsPrevText.GetLength());
268       pEventParam->m_iSelEnd =
269           std::max(pEventParam->m_iSelStart, pEventParam->m_iSelEnd);
270       break;
271     case XFA_Event::Shift:
272       BooleanProperty(pValue, &pEventParam->m_bShift, bSetting);
273       break;
274     case XFA_Event::SoapFaultCode:
275       StringProperty(pValue, &pEventParam->m_wsSoapFaultCode, bSetting);
276       break;
277     case XFA_Event::SoapFaultString:
278       StringProperty(pValue, &pEventParam->m_wsSoapFaultString, bSetting);
279       break;
280     case XFA_Event::Target:
281     default:
282       break;
283   }
284 }
285