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