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_hostpseudomodel.h"
8
9 #include <vector>
10
11 #include "fxjs/fxv8.h"
12 #include "fxjs/js_resources.h"
13 #include "fxjs/xfa/cfxjse_engine.h"
14 #include "third_party/base/check.h"
15 #include "v8/include/v8-object.h"
16 #include "xfa/fxfa/cxfa_ffdoc.h"
17 #include "xfa/fxfa/cxfa_ffnotify.h"
18 #include "xfa/fxfa/parser/cscript_hostpseudomodel.h"
19 #include "xfa/fxfa/parser/cxfa_node.h"
20
21 namespace {
22
FilterName(WideStringView wsExpression,size_t nStart,WideString & wsFilter)23 size_t FilterName(WideStringView wsExpression,
24 size_t nStart,
25 WideString& wsFilter) {
26 const size_t nLength = wsExpression.GetLength();
27 if (nStart >= nLength)
28 return nLength;
29
30 size_t nCount = 0;
31 {
32 // Span's lifetime must end before ReleaseBuffer() below.
33 pdfium::span<wchar_t> pBuf = wsFilter.GetBuffer(nLength - nStart);
34 const wchar_t* pSrc = wsExpression.unterminated_c_str();
35 while (nStart < nLength) {
36 wchar_t wCur = pSrc[nStart++];
37 if (wCur == ',')
38 break;
39
40 pBuf[nCount++] = wCur;
41 }
42 }
43 wsFilter.ReleaseBuffer(nCount);
44 wsFilter.Trim();
45 return nStart;
46 }
47
48 } // namespace
49
50 const CJX_MethodSpec CJX_HostPseudoModel::MethodSpecs[] = {
51 {"beep", beep_static},
52 {"documentCountInBatch", documentCountInBatch_static},
53 {"documentInBatch", documentInBatch_static},
54 {"exportData", exportData_static},
55 {"getFocus", getFocus_static},
56 {"gotoURL", gotoURL_static},
57 {"importData", importData_static},
58 {"messageBox", messageBox_static},
59 {"openList", openList_static},
60 {"pageDown", pageDown_static},
61 {"pageUp", pageUp_static},
62 {"print", print_static},
63 {"resetData", resetData_static},
64 {"response", response_static},
65 {"setFocus", setFocus_static}};
66
CJX_HostPseudoModel(CScript_HostPseudoModel * model)67 CJX_HostPseudoModel::CJX_HostPseudoModel(CScript_HostPseudoModel* model)
68 : CJX_Object(model) {
69 DefineMethods(MethodSpecs);
70 }
71
72 CJX_HostPseudoModel::~CJX_HostPseudoModel() = default;
73
DynamicTypeIs(TypeTag eType) const74 bool CJX_HostPseudoModel::DynamicTypeIs(TypeTag eType) const {
75 return eType == static_type__ || ParentType__::DynamicTypeIs(eType);
76 }
77
appType(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)78 void CJX_HostPseudoModel::appType(v8::Isolate* pIsolate,
79 v8::Local<v8::Value>* pValue,
80 bool bSetting,
81 XFA_Attribute eAttribute) {
82 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
83 if (!pNotify)
84 return;
85
86 if (bSetting) {
87 ThrowInvalidPropertyException(pIsolate);
88 return;
89 }
90 *pValue = fxv8::NewStringHelper(pIsolate, "Exchange");
91 }
92
calculationsEnabled(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)93 void CJX_HostPseudoModel::calculationsEnabled(v8::Isolate* pIsolate,
94 v8::Local<v8::Value>* pValue,
95 bool bSetting,
96 XFA_Attribute eAttribute) {
97 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
98 if (!pNotify)
99 return;
100
101 CXFA_FFDoc* hDoc = pNotify->GetFFDoc();
102 if (bSetting) {
103 hDoc->SetCalculationsEnabled(
104 fxv8::ReentrantToBooleanHelper(pIsolate, *pValue));
105 return;
106 }
107 *pValue = fxv8::NewBooleanHelper(pIsolate, hDoc->IsCalculationsEnabled());
108 }
109
currentPage(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)110 void CJX_HostPseudoModel::currentPage(v8::Isolate* pIsolate,
111 v8::Local<v8::Value>* pValue,
112 bool bSetting,
113 XFA_Attribute eAttribute) {
114 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
115 if (!pNotify)
116 return;
117
118 CXFA_FFDoc* hDoc = pNotify->GetFFDoc();
119 if (bSetting) {
120 hDoc->SetCurrentPage(fxv8::ReentrantToInt32Helper(pIsolate, *pValue));
121 return;
122 }
123 *pValue = fxv8::NewNumberHelper(pIsolate, hDoc->GetCurrentPage());
124 }
125
language(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)126 void CJX_HostPseudoModel::language(v8::Isolate* pIsolate,
127 v8::Local<v8::Value>* pValue,
128 bool bSetting,
129 XFA_Attribute eAttribute) {
130 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
131 if (!pNotify)
132 return;
133
134 if (bSetting) {
135 ThrowException(pIsolate,
136 WideString::FromASCII("Unable to set language value."));
137 return;
138 }
139 ByteString lang = pNotify->GetAppProvider()->GetLanguage().ToUTF8();
140 *pValue = fxv8::NewStringHelper(pIsolate, lang.AsStringView());
141 }
142
numPages(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)143 void CJX_HostPseudoModel::numPages(v8::Isolate* pIsolate,
144 v8::Local<v8::Value>* pValue,
145 bool bSetting,
146 XFA_Attribute eAttribute) {
147 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
148 if (!pNotify)
149 return;
150
151 CXFA_FFDoc* hDoc = pNotify->GetFFDoc();
152 if (bSetting) {
153 ThrowException(pIsolate,
154 WideString::FromASCII("Unable to set numPages value."));
155 return;
156 }
157 *pValue = fxv8::NewNumberHelper(pIsolate, hDoc->CountPages());
158 }
159
platform(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)160 void CJX_HostPseudoModel::platform(v8::Isolate* pIsolate,
161 v8::Local<v8::Value>* pValue,
162 bool bSetting,
163 XFA_Attribute eAttribute) {
164 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
165 if (!pNotify)
166 return;
167
168 if (bSetting) {
169 ThrowException(pIsolate,
170 WideString::FromASCII("Unable to set platform value."));
171 return;
172 }
173 ByteString plat = pNotify->GetAppProvider()->GetPlatform().ToUTF8();
174 *pValue = fxv8::NewStringHelper(pIsolate, plat.AsStringView());
175 }
176
title(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)177 void CJX_HostPseudoModel::title(v8::Isolate* pIsolate,
178 v8::Local<v8::Value>* pValue,
179 bool bSetting,
180 XFA_Attribute eAttribute) {
181 if (!GetDocument()->GetScriptContext()->IsRunAtClient())
182 return;
183
184 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
185 if (!pNotify)
186 return;
187
188 CXFA_FFDoc* hDoc = pNotify->GetFFDoc();
189 if (bSetting) {
190 hDoc->SetTitle(fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
191 return;
192 }
193
194 ByteString bsTitle = hDoc->GetTitle().ToUTF8();
195 *pValue = fxv8::NewStringHelper(pIsolate, bsTitle.AsStringView());
196 }
197
validationsEnabled(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)198 void CJX_HostPseudoModel::validationsEnabled(v8::Isolate* pIsolate,
199 v8::Local<v8::Value>* pValue,
200 bool bSetting,
201 XFA_Attribute eAttribute) {
202 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
203 if (!pNotify)
204 return;
205
206 CXFA_FFDoc* hDoc = pNotify->GetFFDoc();
207 if (bSetting) {
208 hDoc->SetValidationsEnabled(
209 fxv8::ReentrantToBooleanHelper(pIsolate, *pValue));
210 return;
211 }
212
213 *pValue = fxv8::NewBooleanHelper(pIsolate, hDoc->IsValidationsEnabled());
214 }
215
variation(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)216 void CJX_HostPseudoModel::variation(v8::Isolate* pIsolate,
217 v8::Local<v8::Value>* pValue,
218 bool bSetting,
219 XFA_Attribute eAttribute) {
220 if (!GetDocument()->GetScriptContext()->IsRunAtClient())
221 return;
222
223 if (bSetting) {
224 ThrowException(pIsolate,
225 WideString::FromASCII("Unable to set variation value."));
226 return;
227 }
228 *pValue = fxv8::NewStringHelper(pIsolate, "Full");
229 }
230
version(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)231 void CJX_HostPseudoModel::version(v8::Isolate* pIsolate,
232 v8::Local<v8::Value>* pValue,
233 bool bSetting,
234 XFA_Attribute eAttribute) {
235 if (bSetting) {
236 ThrowException(pIsolate,
237 WideString::FromASCII("Unable to set version value."));
238 return;
239 }
240 *pValue = fxv8::NewStringHelper(pIsolate, "11");
241 }
242
name(v8::Isolate * pIsolate,v8::Local<v8::Value> * pValue,bool bSetting,XFA_Attribute eAttribute)243 void CJX_HostPseudoModel::name(v8::Isolate* pIsolate,
244 v8::Local<v8::Value>* pValue,
245 bool bSetting,
246 XFA_Attribute eAttribute) {
247 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
248 if (!pNotify)
249 return;
250
251 if (bSetting) {
252 ThrowInvalidPropertyException(pIsolate);
253 return;
254 }
255 ByteString bsName = pNotify->GetAppProvider()->GetAppName().ToUTF8();
256 *pValue = fxv8::NewStringHelper(pIsolate, bsName.AsStringView());
257 }
258
gotoURL(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)259 CJS_Result CJX_HostPseudoModel::gotoURL(
260 CFXJSE_Engine* runtime,
261 const std::vector<v8::Local<v8::Value>>& params) {
262 if (!runtime->IsRunAtClient()) {
263 return CJS_Result::Success();
264 }
265
266 if (params.size() != 1)
267 return CJS_Result::Failure(JSMessage::kParamError);
268
269 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
270 if (!pNotify)
271 return CJS_Result::Success();
272
273 pNotify->GetFFDoc()->GotoURL(runtime->ToWideString(params[0]));
274 return CJS_Result::Success();
275 }
276
openList(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)277 CJS_Result CJX_HostPseudoModel::openList(
278 CFXJSE_Engine* runtime,
279 const std::vector<v8::Local<v8::Value>>& params) {
280 if (!runtime->IsRunAtClient()) {
281 return CJS_Result::Success();
282 }
283
284 if (params.size() != 1)
285 return CJS_Result::Failure(JSMessage::kParamError);
286
287 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
288 if (!pNotify)
289 return CJS_Result::Success();
290
291 CXFA_Node* pNode = nullptr;
292 if (params[0]->IsObject()) {
293 pNode = ToNode(runtime->ToXFAObject(params[0]));
294 } else if (params[0]->IsString()) {
295 CXFA_Object* pObject = runtime->GetThisObject();
296 if (!pObject)
297 return CJS_Result::Success();
298
299 constexpr Mask<XFA_ResolveFlag> kFlags = {XFA_ResolveFlag::kChildren,
300 XFA_ResolveFlag::kParent,
301 XFA_ResolveFlag::kSiblings};
302 absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
303 runtime->ResolveObjects(
304 pObject, runtime->ToWideString(params[0]).AsStringView(), kFlags);
305 if (!maybeResult.has_value() ||
306 !maybeResult.value().objects.front()->IsNode()) {
307 return CJS_Result::Success();
308 }
309 pNode = maybeResult.value().objects.front()->AsNode();
310 }
311 if (pNode)
312 pNotify->OpenDropDownList(pNode);
313
314 return CJS_Result::Success();
315 }
316
response(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)317 CJS_Result CJX_HostPseudoModel::response(
318 CFXJSE_Engine* runtime,
319 const std::vector<v8::Local<v8::Value>>& params) {
320 if (params.empty() || params.size() > 4)
321 return CJS_Result::Failure(JSMessage::kParamError);
322
323 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
324 if (!pNotify)
325 return CJS_Result::Success();
326
327 WideString question;
328 if (params.size() >= 1)
329 question = runtime->ToWideString(params[0]);
330
331 WideString title;
332 if (params.size() >= 2)
333 title = runtime->ToWideString(params[1]);
334
335 WideString defaultAnswer;
336 if (params.size() >= 3)
337 defaultAnswer = runtime->ToWideString(params[2]);
338
339 bool mark = false;
340 if (params.size() >= 4)
341 mark = runtime->ToInt32(params[3]) != 0;
342
343 WideString answer =
344 pNotify->GetAppProvider()->Response(question, title, defaultAnswer, mark);
345 return CJS_Result::Success(
346 runtime->NewString(answer.ToUTF8().AsStringView()));
347 }
348
documentInBatch(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)349 CJS_Result CJX_HostPseudoModel::documentInBatch(
350 CFXJSE_Engine* runtime,
351 const std::vector<v8::Local<v8::Value>>& params) {
352 return CJS_Result::Success(runtime->NewNumber(0));
353 }
354
resetData(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)355 CJS_Result CJX_HostPseudoModel::resetData(
356 CFXJSE_Engine* runtime,
357 const std::vector<v8::Local<v8::Value>>& params) {
358 if (params.size() > 1)
359 return CJS_Result::Failure(JSMessage::kParamError);
360
361 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
362 if (!pNotify)
363 return CJS_Result::Success();
364
365 WideString expression;
366 if (params.size() >= 1)
367 expression = runtime->ToWideString(params[0]);
368
369 if (expression.IsEmpty()) {
370 pNotify->ResetData(nullptr);
371 return CJS_Result::Success();
372 }
373
374 WideString wsName;
375 CXFA_Node* pNode = nullptr;
376 size_t nStart = 0;
377 const size_t nExpLength = expression.GetLength();
378 while (nStart < nExpLength) {
379 nStart = FilterName(expression.AsStringView(), nStart, wsName);
380 CXFA_Object* pObject = runtime->GetThisObject();
381 if (!pObject)
382 return CJS_Result::Success();
383
384 constexpr Mask<XFA_ResolveFlag> kFlags = {XFA_ResolveFlag::kChildren,
385 XFA_ResolveFlag::kParent,
386 XFA_ResolveFlag::kSiblings};
387 absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
388 runtime->ResolveObjects(pObject, wsName.AsStringView(), kFlags);
389 if (!maybeResult.has_value() ||
390 !maybeResult.value().objects.front()->IsNode())
391 continue;
392
393 pNode = maybeResult.value().objects.front()->AsNode();
394 pNotify->ResetData(pNode->IsWidgetReady() ? pNode : nullptr);
395 }
396 if (!pNode)
397 pNotify->ResetData(nullptr);
398
399 return CJS_Result::Success();
400 }
401
beep(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)402 CJS_Result CJX_HostPseudoModel::beep(
403 CFXJSE_Engine* runtime,
404 const std::vector<v8::Local<v8::Value>>& params) {
405 if (!runtime->IsRunAtClient()) {
406 return CJS_Result::Success();
407 }
408
409 if (params.size() > 1)
410 return CJS_Result::Failure(JSMessage::kParamError);
411
412 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
413 if (!pNotify)
414 return CJS_Result::Success();
415
416 uint32_t dwType = 4;
417 if (params.size() >= 1)
418 dwType = runtime->ToInt32(params[0]);
419
420 pNotify->GetAppProvider()->Beep(dwType);
421 return CJS_Result::Success();
422 }
423
setFocus(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)424 CJS_Result CJX_HostPseudoModel::setFocus(
425 CFXJSE_Engine* runtime,
426 const std::vector<v8::Local<v8::Value>>& params) {
427 if (!runtime->IsRunAtClient()) {
428 return CJS_Result::Success();
429 }
430
431 if (params.size() != 1)
432 return CJS_Result::Failure(JSMessage::kParamError);
433
434 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
435 if (!pNotify)
436 return CJS_Result::Success();
437
438 CXFA_Node* pNode = nullptr;
439 if (params.size() >= 1) {
440 if (params[0]->IsObject()) {
441 pNode = ToNode(runtime->ToXFAObject(params[0]));
442 } else if (params[0]->IsString()) {
443 CXFA_Object* pObject = runtime->GetThisObject();
444 if (!pObject)
445 return CJS_Result::Success();
446
447 constexpr Mask<XFA_ResolveFlag> kFlags = {XFA_ResolveFlag::kChildren,
448 XFA_ResolveFlag::kParent,
449 XFA_ResolveFlag::kSiblings};
450 absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
451 runtime->ResolveObjects(
452 pObject, runtime->ToWideString(params[0]).AsStringView(), kFlags);
453 if (!maybeResult.has_value() ||
454 !maybeResult.value().objects.front()->IsNode()) {
455 return CJS_Result::Success();
456 }
457 pNode = maybeResult.value().objects.front()->AsNode();
458 }
459 }
460 pNotify->SetFocusWidgetNode(pNode);
461 return CJS_Result::Success();
462 }
463
getFocus(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)464 CJS_Result CJX_HostPseudoModel::getFocus(
465 CFXJSE_Engine* runtime,
466 const std::vector<v8::Local<v8::Value>>& params) {
467 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
468 if (!pNotify)
469 return CJS_Result::Success();
470
471 CXFA_Node* pNode = pNotify->GetFocusWidgetNode();
472 if (!pNode)
473 return CJS_Result::Success();
474
475 return CJS_Result::Success(runtime->GetOrCreateJSBindingFromMap(pNode));
476 }
477
messageBox(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)478 CJS_Result CJX_HostPseudoModel::messageBox(
479 CFXJSE_Engine* runtime,
480 const std::vector<v8::Local<v8::Value>>& params) {
481 if (!runtime->IsRunAtClient()) {
482 return CJS_Result::Success();
483 }
484
485 if (params.empty() || params.size() > 4)
486 return CJS_Result::Failure(JSMessage::kParamError);
487
488 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
489 if (!pNotify)
490 return CJS_Result::Success();
491
492 WideString message;
493 if (params.size() >= 1)
494 message = runtime->ToWideString(params[0]);
495
496 WideString title;
497 if (params.size() >= 2)
498 title = runtime->ToWideString(params[1]);
499
500 uint32_t messageType = static_cast<uint32_t>(AlertIcon::kDefault);
501 if (params.size() >= 3) {
502 messageType = runtime->ToInt32(params[2]);
503 if (messageType > static_cast<uint32_t>(AlertIcon::kStatus))
504 messageType = static_cast<uint32_t>(AlertIcon::kDefault);
505 }
506
507 uint32_t buttonType = static_cast<uint32_t>(AlertButton::kDefault);
508 if (params.size() >= 4) {
509 buttonType = runtime->ToInt32(params[3]);
510 if (buttonType > static_cast<uint32_t>(AlertButton::kYesNoCancel))
511 buttonType = static_cast<uint32_t>(AlertButton::kDefault);
512 }
513
514 int32_t iValue = pNotify->GetAppProvider()->MsgBox(message, title,
515 messageType, buttonType);
516 return CJS_Result::Success(runtime->NewNumber(iValue));
517 }
518
documentCountInBatch(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)519 CJS_Result CJX_HostPseudoModel::documentCountInBatch(
520 CFXJSE_Engine* runtime,
521 const std::vector<v8::Local<v8::Value>>& params) {
522 return CJS_Result::Success(runtime->NewNumber(0));
523 }
524
print(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)525 CJS_Result CJX_HostPseudoModel::print(
526 CFXJSE_Engine* runtime,
527 const std::vector<v8::Local<v8::Value>>& params) {
528 if (!runtime->IsRunAtClient()) {
529 return CJS_Result::Success();
530 }
531
532 if (params.size() != 8)
533 return CJS_Result::Failure(JSMessage::kParamError);
534
535 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
536 if (!pNotify)
537 return CJS_Result::Success();
538
539 Mask<XFA_PrintOpt> dwOptions;
540 if (runtime->ToBoolean(params[0]))
541 dwOptions |= XFA_PrintOpt::kShowDialog;
542 if (runtime->ToBoolean(params[3]))
543 dwOptions |= XFA_PrintOpt::kCanCancel;
544 if (runtime->ToBoolean(params[4]))
545 dwOptions |= XFA_PrintOpt::kShrinkPage;
546 if (runtime->ToBoolean(params[5]))
547 dwOptions |= XFA_PrintOpt::kAsImage;
548 if (runtime->ToBoolean(params[6]))
549 dwOptions |= XFA_PrintOpt::kReverseOrder;
550 if (runtime->ToBoolean(params[7]))
551 dwOptions |= XFA_PrintOpt::kPrintAnnot;
552
553 int32_t nStartPage = runtime->ToInt32(params[1]);
554 int32_t nEndPage = runtime->ToInt32(params[2]);
555 pNotify->GetFFDoc()->Print(nStartPage, nEndPage, dwOptions);
556 return CJS_Result::Success();
557 }
558
importData(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)559 CJS_Result CJX_HostPseudoModel::importData(
560 CFXJSE_Engine* runtime,
561 const std::vector<v8::Local<v8::Value>>& params) {
562 if (params.empty() || params.size() > 1)
563 return CJS_Result::Failure(JSMessage::kParamError);
564
565 return CJS_Result::Success();
566 }
567
exportData(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)568 CJS_Result CJX_HostPseudoModel::exportData(
569 CFXJSE_Engine* runtime,
570 const std::vector<v8::Local<v8::Value>>& params) {
571 if (params.empty() || params.size() > 2)
572 return CJS_Result::Failure(JSMessage::kParamError);
573
574 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
575 if (!pNotify)
576 return CJS_Result::Success();
577
578 WideString filePath;
579 if (params.size() >= 1)
580 filePath = runtime->ToWideString(params[0]);
581
582 bool XDP = true;
583 if (params.size() >= 2)
584 XDP = runtime->ToBoolean(params[1]);
585
586 pNotify->GetFFDoc()->ExportData(filePath, XDP);
587 return CJS_Result::Success();
588 }
589
pageUp(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)590 CJS_Result CJX_HostPseudoModel::pageUp(
591 CFXJSE_Engine* runtime,
592 const std::vector<v8::Local<v8::Value>>& params) {
593 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
594 if (!pNotify)
595 return CJS_Result::Success();
596
597 CXFA_FFDoc* hDoc = pNotify->GetFFDoc();
598 int32_t nCurPage = hDoc->GetCurrentPage();
599 if (nCurPage <= 1)
600 return CJS_Result::Success();
601
602 hDoc->SetCurrentPage(nCurPage - 1);
603 return CJS_Result::Success();
604 }
605
pageDown(CFXJSE_Engine * runtime,const std::vector<v8::Local<v8::Value>> & params)606 CJS_Result CJX_HostPseudoModel::pageDown(
607 CFXJSE_Engine* runtime,
608 const std::vector<v8::Local<v8::Value>>& params) {
609 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
610 if (!pNotify)
611 return CJS_Result::Success();
612
613 CXFA_FFDoc* hDoc = pNotify->GetFFDoc();
614 int32_t nCurPage = hDoc->GetCurrentPage();
615 int32_t nPageCount = hDoc->CountPages();
616 if (!nPageCount || nCurPage == nPageCount)
617 return CJS_Result::Success();
618
619 int32_t nNewPage = 0;
620 if (nCurPage >= nPageCount)
621 nNewPage = nPageCount - 1;
622 else
623 nNewPage = nCurPage + 1;
624
625 hDoc->SetCurrentPage(nNewPage);
626 return CJS_Result::Success();
627 }
628