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/cjs_event_context.h"
8
9 #include "core/fpdfdoc/cpdf_formfield.h"
10 #include "core/fxcrt/autorestorer.h"
11 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
12 #include "fxjs/cjs_field.h"
13 #include "fxjs/cjs_runtime.h"
14 #include "fxjs/js_define.h"
15 #include "fxjs/js_resources.h"
16 #include "third_party/base/check.h"
17 #include "v8/include/v8-context.h"
18 #include "v8/include/v8-isolate.h"
19
CJS_EventContext(CJS_Runtime * pRuntime)20 CJS_EventContext::CJS_EventContext(CJS_Runtime* pRuntime)
21 : m_pRuntime(pRuntime), m_pFormFillEnv(pRuntime->GetFormFillEnv()) {}
22
23 CJS_EventContext::~CJS_EventContext() = default;
24
RunScript(const WideString & script)25 absl::optional<IJS_Runtime::JS_Error> CJS_EventContext::RunScript(
26 const WideString& script) {
27 v8::Isolate::Scope isolate_scope(m_pRuntime->GetIsolate());
28 v8::HandleScope handle_scope(m_pRuntime->GetIsolate());
29 v8::Local<v8::Context> context = m_pRuntime->GetV8Context();
30 v8::Context::Scope context_scope(context);
31
32 if (m_bBusy) {
33 return IJS_Runtime::JS_Error(1, 1,
34 JSGetStringFromID(JSMessage::kBusyError));
35 }
36
37 AutoRestorer<bool> restorer(&m_bBusy);
38 m_bBusy = true;
39
40 DCHECK(IsValid());
41 CJS_Runtime::FieldEvent event(TargetName(), EventKind());
42 if (!m_pRuntime->AddEventToSet(event)) {
43 return IJS_Runtime::JS_Error(
44 1, 1, JSGetStringFromID(JSMessage::kDuplicateEventError));
45 }
46
47 absl::optional<IJS_Runtime::JS_Error> err;
48 if (script.GetLength() > 0)
49 err = m_pRuntime->ExecuteScript(script);
50
51 m_pRuntime->RemoveEventFromSet(event);
52 Destroy();
53 return err;
54 }
55
SourceField()56 CJS_Field* CJS_EventContext::SourceField() {
57 v8::Local<v8::Object> pDocObj = m_pRuntime->NewFXJSBoundObject(
58 CJS_Document::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
59 if (pDocObj.IsEmpty())
60 return nullptr;
61
62 v8::Local<v8::Object> pFieldObj = m_pRuntime->NewFXJSBoundObject(
63 CJS_Field::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
64 if (pFieldObj.IsEmpty())
65 return nullptr;
66
67 auto* pFormFillEnv = GetFormFillEnv();
68 auto* pJSDocument = static_cast<CJS_Document*>(
69 CFXJS_Engine::GetObjectPrivate(m_pRuntime->GetIsolate(), pDocObj));
70 pJSDocument->SetFormFillEnv(pFormFillEnv);
71
72 auto* pJSField = static_cast<CJS_Field*>(
73 CFXJS_Engine::GetObjectPrivate(m_pRuntime->GetIsolate(), pFieldObj));
74 pJSField->AttachField(pJSDocument, SourceName());
75 return pJSField;
76 }
77
TargetField()78 CJS_Field* CJS_EventContext::TargetField() {
79 v8::Local<v8::Object> pDocObj = m_pRuntime->NewFXJSBoundObject(
80 CJS_Document::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
81 if (pDocObj.IsEmpty())
82 return nullptr;
83
84 v8::Local<v8::Object> pFieldObj = m_pRuntime->NewFXJSBoundObject(
85 CJS_Field::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
86 if (pFieldObj.IsEmpty())
87 return nullptr;
88
89 auto* pFormFillEnv = GetFormFillEnv();
90 auto* pJSDocument = static_cast<CJS_Document*>(
91 CFXJS_Engine::GetObjectPrivate(m_pRuntime->GetIsolate(), pDocObj));
92 pJSDocument->SetFormFillEnv(pFormFillEnv);
93
94 auto* pJSField = static_cast<CJS_Field*>(
95 CFXJS_Engine::GetObjectPrivate(m_pRuntime->GetIsolate(), pFieldObj));
96 pJSField->AttachField(pJSDocument, TargetName());
97 return pJSField;
98 }
99
OnDoc_Open(const WideString & strTargetName)100 void CJS_EventContext::OnDoc_Open(const WideString& strTargetName) {
101 Initialize(Kind::kDocOpen);
102 m_strTargetName = strTargetName;
103 }
104
OnDoc_WillPrint()105 void CJS_EventContext::OnDoc_WillPrint() {
106 Initialize(Kind::kDocWillPrint);
107 }
108
OnDoc_DidPrint()109 void CJS_EventContext::OnDoc_DidPrint() {
110 Initialize(Kind::kDocDidPrint);
111 }
112
OnDoc_WillSave()113 void CJS_EventContext::OnDoc_WillSave() {
114 Initialize(Kind::kDocWillSave);
115 }
116
OnDoc_DidSave()117 void CJS_EventContext::OnDoc_DidSave() {
118 Initialize(Kind::kDocDidSave);
119 }
120
OnDoc_WillClose()121 void CJS_EventContext::OnDoc_WillClose() {
122 Initialize(Kind::kDocWillClose);
123 }
124
OnPage_Open()125 void CJS_EventContext::OnPage_Open() {
126 Initialize(Kind::kPageOpen);
127 }
128
OnPage_Close()129 void CJS_EventContext::OnPage_Close() {
130 Initialize(Kind::kPageClose);
131 }
132
OnPage_InView()133 void CJS_EventContext::OnPage_InView() {
134 Initialize(Kind::kPageInView);
135 }
136
OnPage_OutView()137 void CJS_EventContext::OnPage_OutView() {
138 Initialize(Kind::kPageOutView);
139 }
140
OnField_MouseEnter(bool bModifier,bool bShift,CPDF_FormField * pTarget)141 void CJS_EventContext::OnField_MouseEnter(bool bModifier,
142 bool bShift,
143 CPDF_FormField* pTarget) {
144 Initialize(Kind::kFieldMouseEnter);
145 m_bModifier = bModifier;
146 m_bShift = bShift;
147 m_strTargetName = pTarget->GetFullName();
148 }
149
OnField_MouseExit(bool bModifier,bool bShift,CPDF_FormField * pTarget)150 void CJS_EventContext::OnField_MouseExit(bool bModifier,
151 bool bShift,
152 CPDF_FormField* pTarget) {
153 Initialize(Kind::kFieldMouseExit);
154 m_bModifier = bModifier;
155 m_bShift = bShift;
156 m_strTargetName = pTarget->GetFullName();
157 }
158
OnField_MouseDown(bool bModifier,bool bShift,CPDF_FormField * pTarget)159 void CJS_EventContext::OnField_MouseDown(bool bModifier,
160 bool bShift,
161 CPDF_FormField* pTarget) {
162 Initialize(Kind::kFieldMouseDown);
163 m_bModifier = bModifier;
164 m_bShift = bShift;
165 m_strTargetName = pTarget->GetFullName();
166 }
167
OnField_MouseUp(bool bModifier,bool bShift,CPDF_FormField * pTarget)168 void CJS_EventContext::OnField_MouseUp(bool bModifier,
169 bool bShift,
170 CPDF_FormField* pTarget) {
171 Initialize(Kind::kFieldMouseUp);
172 m_bModifier = bModifier;
173 m_bShift = bShift;
174 m_strTargetName = pTarget->GetFullName();
175 }
176
OnField_Focus(bool bModifier,bool bShift,CPDF_FormField * pTarget,WideString * pValue)177 void CJS_EventContext::OnField_Focus(bool bModifier,
178 bool bShift,
179 CPDF_FormField* pTarget,
180 WideString* pValue) {
181 DCHECK(pValue);
182 Initialize(Kind::kFieldFocus);
183 m_bModifier = bModifier;
184 m_bShift = bShift;
185 m_strTargetName = pTarget->GetFullName();
186 m_pValue = pValue;
187 }
188
OnField_Blur(bool bModifier,bool bShift,CPDF_FormField * pTarget,WideString * pValue)189 void CJS_EventContext::OnField_Blur(bool bModifier,
190 bool bShift,
191 CPDF_FormField* pTarget,
192 WideString* pValue) {
193 DCHECK(pValue);
194 Initialize(Kind::kFieldBlur);
195 m_bModifier = bModifier;
196 m_bShift = bShift;
197 m_strTargetName = pTarget->GetFullName();
198 m_pValue = pValue;
199 }
200
OnField_Keystroke(WideString * strChange,const WideString & strChangeEx,bool KeyDown,bool bModifier,int * pSelEnd,int * pSelStart,bool bShift,CPDF_FormField * pTarget,WideString * pValue,bool bWillCommit,bool bFieldFull,bool * pbRc)201 void CJS_EventContext::OnField_Keystroke(WideString* strChange,
202 const WideString& strChangeEx,
203 bool KeyDown,
204 bool bModifier,
205 int* pSelEnd,
206 int* pSelStart,
207 bool bShift,
208 CPDF_FormField* pTarget,
209 WideString* pValue,
210 bool bWillCommit,
211 bool bFieldFull,
212 bool* pbRc) {
213 DCHECK(pValue);
214 DCHECK(pbRc);
215 DCHECK(pSelStart);
216 DCHECK(pSelEnd);
217
218 Initialize(Kind::kFieldKeystroke);
219 m_nCommitKey = 0;
220 m_pWideStrChange = strChange;
221 m_WideStrChangeEx = strChangeEx;
222 m_bKeyDown = KeyDown;
223 m_bModifier = bModifier;
224 m_pISelEnd = pSelEnd;
225 m_pISelStart = pSelStart;
226 m_bShift = bShift;
227 m_strTargetName = pTarget->GetFullName();
228 m_pValue = pValue;
229 m_bWillCommit = bWillCommit;
230 m_pbRc = pbRc;
231 m_bFieldFull = bFieldFull;
232 }
233
OnField_Validate(WideString * strChange,const WideString & strChangeEx,bool bKeyDown,bool bModifier,bool bShift,CPDF_FormField * pTarget,WideString * pValue,bool * pbRc)234 void CJS_EventContext::OnField_Validate(WideString* strChange,
235 const WideString& strChangeEx,
236 bool bKeyDown,
237 bool bModifier,
238 bool bShift,
239 CPDF_FormField* pTarget,
240 WideString* pValue,
241 bool* pbRc) {
242 DCHECK(pValue);
243 DCHECK(pbRc);
244 Initialize(Kind::kFieldValidate);
245 m_pWideStrChange = strChange;
246 m_WideStrChangeEx = strChangeEx;
247 m_bKeyDown = bKeyDown;
248 m_bModifier = bModifier;
249 m_bShift = bShift;
250 m_strTargetName = pTarget->GetFullName();
251 m_pValue = pValue;
252 m_pbRc = pbRc;
253 }
254
OnField_Calculate(CPDF_FormField * pSource,CPDF_FormField * pTarget,WideString * pValue,bool * pRc)255 void CJS_EventContext::OnField_Calculate(CPDF_FormField* pSource,
256 CPDF_FormField* pTarget,
257 WideString* pValue,
258 bool* pRc) {
259 DCHECK(pValue);
260 DCHECK(pRc);
261 Initialize(Kind::kFieldCalculate);
262 if (pSource)
263 m_strSourceName = pSource->GetFullName();
264 m_strTargetName = pTarget->GetFullName();
265 m_pValue = pValue;
266 m_pbRc = pRc;
267 }
268
OnField_Format(CPDF_FormField * pTarget,WideString * pValue)269 void CJS_EventContext::OnField_Format(CPDF_FormField* pTarget,
270 WideString* pValue) {
271 DCHECK(pValue);
272 Initialize(Kind::kFieldFormat);
273 m_nCommitKey = 0;
274 m_strTargetName = pTarget->GetFullName();
275 m_pValue = pValue;
276 m_bWillCommit = true;
277 }
278
OnExternal_Exec()279 void CJS_EventContext::OnExternal_Exec() {
280 Initialize(Kind::kExternalExec);
281 }
282
Initialize(Kind kind)283 void CJS_EventContext::Initialize(Kind kind) {
284 m_eKind = kind;
285 m_strTargetName.clear();
286 m_strSourceName.clear();
287 m_pWideStrChange = nullptr;
288 m_WideStrChangeDu.clear();
289 m_WideStrChangeEx.clear();
290 m_nCommitKey = -1;
291 m_bKeyDown = false;
292 m_bModifier = false;
293 m_bShift = false;
294 m_pISelEnd = nullptr;
295 m_nSelEndDu = 0;
296 m_pISelStart = nullptr;
297 m_nSelStartDu = 0;
298 m_bWillCommit = false;
299 m_pValue = nullptr;
300 m_bFieldFull = false;
301 m_pbRc = nullptr;
302 m_bRcDu = false;
303 m_bValid = true;
304 }
305
Destroy()306 void CJS_EventContext::Destroy() {
307 m_bValid = false;
308 }
309
IsUserGesture() const310 bool CJS_EventContext::IsUserGesture() const {
311 switch (m_eKind) {
312 case Kind::kFieldMouseDown:
313 case Kind::kFieldMouseUp:
314 case Kind::kFieldKeystroke:
315 return true;
316 default:
317 return false;
318 }
319 }
320
Change()321 WideString& CJS_EventContext::Change() {
322 return m_pWideStrChange ? *m_pWideStrChange : m_WideStrChangeDu;
323 }
324
Name() const325 ByteStringView CJS_EventContext::Name() const {
326 switch (m_eKind) {
327 case Kind::kDocDidPrint:
328 return "DidPrint";
329 case Kind::kDocDidSave:
330 return "DidSave";
331 case Kind::kDocOpen:
332 return "Open";
333 case Kind::kDocWillClose:
334 return "WillClose";
335 case Kind::kDocWillPrint:
336 return "WillPrint";
337 case Kind::kDocWillSave:
338 return "WillSave";
339 case Kind::kExternalExec:
340 return "Exec";
341 case Kind::kFieldFocus:
342 return "Focus";
343 case Kind::kFieldBlur:
344 return "Blur";
345 case Kind::kFieldMouseDown:
346 return "Mouse Down";
347 case Kind::kFieldMouseUp:
348 return "Mouse Up";
349 case Kind::kFieldMouseEnter:
350 return "Mouse Enter";
351 case Kind::kFieldMouseExit:
352 return "Mouse Exit";
353 case Kind::kFieldCalculate:
354 return "Calculate";
355 case Kind::kFieldFormat:
356 return "Format";
357 case Kind::kFieldKeystroke:
358 return "Keystroke";
359 case Kind::kFieldValidate:
360 return "Validate";
361 case Kind::kPageOpen:
362 return "Open";
363 case Kind::kPageClose:
364 return "Close";
365 case Kind::kPageInView:
366 return "InView";
367 case Kind::kPageOutView:
368 return "OutView";
369 default:
370 return "";
371 }
372 }
373
Type() const374 ByteStringView CJS_EventContext::Type() const {
375 switch (m_eKind) {
376 case Kind::kDocDidPrint:
377 case Kind::kDocDidSave:
378 case Kind::kDocOpen:
379 case Kind::kDocWillClose:
380 case Kind::kDocWillPrint:
381 case Kind::kDocWillSave:
382 return "Doc";
383 case Kind::kExternalExec:
384 return "External";
385 case Kind::kFieldBlur:
386 case Kind::kFieldFocus:
387 case Kind::kFieldMouseDown:
388 case Kind::kFieldMouseUp:
389 case Kind::kFieldMouseEnter:
390 case Kind::kFieldMouseExit:
391 case Kind::kFieldCalculate:
392 case Kind::kFieldFormat:
393 case Kind::kFieldKeystroke:
394 case Kind::kFieldValidate:
395 return "Field";
396 case Kind::kPageOpen:
397 case Kind::kPageClose:
398 case Kind::kPageInView:
399 case Kind::kPageOutView:
400 return "Page";
401 default:
402 return "";
403 }
404 }
405
Rc()406 bool& CJS_EventContext::Rc() {
407 return m_pbRc ? *m_pbRc : m_bRcDu;
408 }
409
SelEnd() const410 int CJS_EventContext::SelEnd() const {
411 return m_pISelEnd ? *m_pISelEnd : m_nSelEndDu;
412 }
413
SelStart() const414 int CJS_EventContext::SelStart() const {
415 return m_pISelStart ? *m_pISelStart : m_nSelStartDu;
416 }
417
SetSelEnd(int value)418 void CJS_EventContext::SetSelEnd(int value) {
419 int& target = m_pISelEnd ? *m_pISelEnd : m_nSelEndDu;
420 target = value;
421 }
422
SetSelStart(int value)423 void CJS_EventContext::SetSelStart(int value) {
424 int& target = m_pISelStart ? *m_pISelStart : m_nSelStartDu;
425 target = value;
426 }
427