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