• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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_app.h"
8 
9 #include <stdint.h>
10 
11 #include <algorithm>
12 #include <utility>
13 
14 #include "core/fxcrt/fixed_zeroed_data_vector.h"
15 #include "core/fxcrt/stl_util.h"
16 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
17 #include "fpdfsdk/cpdfsdk_interactiveform.h"
18 #include "fxjs/cjs_document.h"
19 #include "fxjs/cjs_timerobj.h"
20 #include "fxjs/global_timer.h"
21 #include "fxjs/ijs_event_context.h"
22 #include "fxjs/js_resources.h"
23 #include "v8/include/v8-container.h"
24 
25 namespace {
26 
27 constexpr wchar_t kStrViewerType[] = L"pdfium";
28 constexpr wchar_t kStrViewerVariation[] = L"Full";
29 constexpr wchar_t kStrPlatform[] = L"WIN";
30 constexpr wchar_t kStrLanguage[] = L"ENU";
31 constexpr int kNumViewerVersion = 8;
32 constexpr int kNumViewerVersionXfa = 11;
33 constexpr int kNumFormsVersion = 7;
34 
35 }  // namespace
36 
37 const JSPropertySpec CJS_App::PropertySpecs[] = {
38     {"activeDocs", get_active_docs_static, set_active_docs_static},
39     {"calculate", get_calculate_static, set_calculate_static},
40     {"formsVersion", get_forms_version_static, set_forms_version_static},
41     {"fs", get_fs_static, set_fs_static},
42     {"fullscreen", get_fullscreen_static, set_fullscreen_static},
43     {"language", get_language_static, set_language_static},
44     {"media", get_media_static, set_media_static},
45     {"platform", get_platform_static, set_platform_static},
46     {"runtimeHighlight", get_runtime_highlight_static,
47      set_runtime_highlight_static},
48     {"viewerType", get_viewer_type_static, set_viewer_type_static},
49     {"viewerVariation", get_viewer_variation_static,
50      set_viewer_variation_static},
51     {"viewerVersion", get_viewer_version_static, set_viewer_version_static}};
52 
53 const JSMethodSpec CJS_App::MethodSpecs[] = {
54     {"alert", alert_static},
55     {"beep", beep_static},
56     {"browseForDoc", browseForDoc_static},
57     {"clearInterval", clearInterval_static},
58     {"clearTimeOut", clearTimeOut_static},
59     {"execDialog", execDialog_static},
60     {"execMenuItem", execMenuItem_static},
61     {"findComponent", findComponent_static},
62     {"goBack", goBack_static},
63     {"goForward", goForward_static},
64     {"launchURL", launchURL_static},
65     {"mailMsg", mailMsg_static},
66     {"newFDF", newFDF_static},
67     {"newDoc", newDoc_static},
68     {"openDoc", openDoc_static},
69     {"openFDF", openFDF_static},
70     {"popUpMenuEx", popUpMenuEx_static},
71     {"popUpMenu", popUpMenu_static},
72     {"response", response_static},
73     {"setInterval", setInterval_static},
74     {"setTimeOut", setTimeOut_static}};
75 
76 uint32_t CJS_App::ObjDefnID = 0;
77 
78 const char CJS_App::kName[] = "app";
79 
80 // static
GetObjDefnID()81 uint32_t CJS_App::GetObjDefnID() {
82   return ObjDefnID;
83 }
84 
85 // static
DefineJSObjects(CFXJS_Engine * pEngine)86 void CJS_App::DefineJSObjects(CFXJS_Engine* pEngine) {
87   ObjDefnID = pEngine->DefineObj(CJS_App::kName, FXJSOBJTYPE_STATIC,
88                                  JSConstructor<CJS_App>, JSDestructor);
89   DefineProps(pEngine, ObjDefnID, PropertySpecs);
90   DefineMethods(pEngine, ObjDefnID, MethodSpecs);
91 }
92 
CJS_App(v8::Local<v8::Object> pObject,CJS_Runtime * pRuntime)93 CJS_App::CJS_App(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime)
94     : CJS_Object(pObject, pRuntime) {}
95 
96 CJS_App::~CJS_App() = default;
97 
get_active_docs(CJS_Runtime * pRuntime)98 CJS_Result CJS_App::get_active_docs(CJS_Runtime* pRuntime) {
99   v8::Local<v8::Object> pObj = pRuntime->GetThisObj();
100   auto pJSDocument = JSGetObject<CJS_Document>(pRuntime->GetIsolate(), pObj);
101   if (!pJSDocument)
102     return CJS_Result::Failure(JSMessage::kObjectTypeError);
103   v8::Local<v8::Array> aDocs = pRuntime->NewArray();
104   pRuntime->PutArrayElement(aDocs, 0, pJSDocument->ToV8Object());
105   if (pRuntime->GetArrayLength(aDocs) > 0)
106     return CJS_Result::Success(aDocs);
107 
108   return CJS_Result::Success(pRuntime->NewUndefined());
109 }
110 
set_active_docs(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)111 CJS_Result CJS_App::set_active_docs(CJS_Runtime* pRuntime,
112                                     v8::Local<v8::Value> vp) {
113   return CJS_Result::Failure(JSMessage::kNotSupportedError);
114 }
115 
get_calculate(CJS_Runtime * pRuntime)116 CJS_Result CJS_App::get_calculate(CJS_Runtime* pRuntime) {
117   return CJS_Result::Success(pRuntime->NewBoolean(m_bCalculate));
118 }
119 
set_calculate(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)120 CJS_Result CJS_App::set_calculate(CJS_Runtime* pRuntime,
121                                   v8::Local<v8::Value> vp) {
122   m_bCalculate = pRuntime->ToBoolean(vp);
123   pRuntime->GetFormFillEnv()->GetInteractiveForm()->EnableCalculate(
124       m_bCalculate);
125   return CJS_Result::Success();
126 }
127 
get_forms_version(CJS_Runtime * pRuntime)128 CJS_Result CJS_App::get_forms_version(CJS_Runtime* pRuntime) {
129   return CJS_Result::Success(pRuntime->NewNumber(kNumFormsVersion));
130 }
131 
set_forms_version(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)132 CJS_Result CJS_App::set_forms_version(CJS_Runtime* pRuntime,
133                                       v8::Local<v8::Value> vp) {
134   return CJS_Result::Failure(JSMessage::kNotSupportedError);
135 }
136 
get_viewer_type(CJS_Runtime * pRuntime)137 CJS_Result CJS_App::get_viewer_type(CJS_Runtime* pRuntime) {
138   return CJS_Result::Success(pRuntime->NewString(kStrViewerType));
139 }
140 
set_viewer_type(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)141 CJS_Result CJS_App::set_viewer_type(CJS_Runtime* pRuntime,
142                                     v8::Local<v8::Value> vp) {
143   return CJS_Result::Failure(JSMessage::kNotSupportedError);
144 }
145 
get_viewer_variation(CJS_Runtime * pRuntime)146 CJS_Result CJS_App::get_viewer_variation(CJS_Runtime* pRuntime) {
147   return CJS_Result::Success(pRuntime->NewString(kStrViewerVariation));
148 }
149 
set_viewer_variation(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)150 CJS_Result CJS_App::set_viewer_variation(CJS_Runtime* pRuntime,
151                                          v8::Local<v8::Value> vp) {
152   return CJS_Result::Failure(JSMessage::kNotSupportedError);
153 }
154 
get_viewer_version(CJS_Runtime * pRuntime)155 CJS_Result CJS_App::get_viewer_version(CJS_Runtime* pRuntime) {
156   CPDF_Document::Extension* pContext =
157       pRuntime->GetFormFillEnv()->GetDocExtension();
158   int version = pContext && pContext->ContainsExtensionForm()
159                     ? kNumViewerVersionXfa
160                     : kNumViewerVersion;
161   return CJS_Result::Success(pRuntime->NewNumber(version));
162 }
163 
set_viewer_version(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)164 CJS_Result CJS_App::set_viewer_version(CJS_Runtime* pRuntime,
165                                        v8::Local<v8::Value> vp) {
166   return CJS_Result::Failure(JSMessage::kNotSupportedError);
167 }
168 
get_platform(CJS_Runtime * pRuntime)169 CJS_Result CJS_App::get_platform(CJS_Runtime* pRuntime) {
170   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
171   if (pFormFillEnv) {
172     WideString platform = pFormFillEnv->GetPlatform();
173     if (!platform.IsEmpty())
174       return CJS_Result::Success(pRuntime->NewString(platform.AsStringView()));
175   }
176   return CJS_Result::Success(pRuntime->NewString(kStrPlatform));
177 }
178 
set_platform(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)179 CJS_Result CJS_App::set_platform(CJS_Runtime* pRuntime,
180                                  v8::Local<v8::Value> vp) {
181   return CJS_Result::Failure(JSMessage::kNotSupportedError);
182 }
183 
get_language(CJS_Runtime * pRuntime)184 CJS_Result CJS_App::get_language(CJS_Runtime* pRuntime) {
185   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
186   if (pFormFillEnv) {
187     WideString language = pFormFillEnv->GetLanguage();
188     if (!language.IsEmpty())
189       return CJS_Result::Success(pRuntime->NewString(language.AsStringView()));
190   }
191   return CJS_Result::Success(pRuntime->NewString(kStrLanguage));
192 }
193 
set_language(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)194 CJS_Result CJS_App::set_language(CJS_Runtime* pRuntime,
195                                  v8::Local<v8::Value> vp) {
196   return CJS_Result::Failure(JSMessage::kNotSupportedError);
197 }
198 
199 // creates a new fdf object that contains no data
200 // comment: need reader support
201 // note:
202 // CFDF_Document * CPDFSDK_FormFillEnvironment::NewFDF();
newFDF(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)203 CJS_Result CJS_App::newFDF(CJS_Runtime* pRuntime,
204                            const std::vector<v8::Local<v8::Value>>& params) {
205   return CJS_Result::Success();
206 }
207 
208 // opens a specified pdf document and returns its document object
209 // comment:need reader support
210 // note: as defined in js reference, the proto of this function's fourth
211 // parmeters, how old an fdf document while do not show it.
212 // CFDF_Document * CPDFSDK_FormFillEnvironment::OpenFDF(string strPath,bool
213 // bUserConv);
214 
openFDF(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)215 CJS_Result CJS_App::openFDF(CJS_Runtime* pRuntime,
216                             const std::vector<v8::Local<v8::Value>>& params) {
217   return CJS_Result::Success();
218 }
219 
alert(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)220 CJS_Result CJS_App::alert(CJS_Runtime* pRuntime,
221                           const std::vector<v8::Local<v8::Value>>& params) {
222   std::vector<v8::Local<v8::Value>> newParams = ExpandKeywordParams(
223       pRuntime, params, 4, "cMsg", "nIcon", "nType", "cTitle");
224 
225   if (!IsExpandedParamKnown(newParams[0]))
226     return CJS_Result::Failure(JSMessage::kParamError);
227 
228   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
229   if (!pFormFillEnv)
230     return CJS_Result::Success(pRuntime->NewNumber(0));
231 
232   WideString swMsg;
233   if (newParams[0]->IsArray()) {
234     v8::Local<v8::Array> carray = pRuntime->ToArray(newParams[0]);
235     swMsg = L"[";
236     for (size_t i = 0; i < pRuntime->GetArrayLength(carray); ++i) {
237       if (i)
238         swMsg += L", ";
239 
240       swMsg += pRuntime->ToWideString(pRuntime->GetArrayElement(carray, i));
241     }
242     swMsg += L"]";
243   } else {
244     swMsg = pRuntime->ToWideString(newParams[0]);
245   }
246 
247   int iIcon = JSPLATFORM_ALERT_ICON_DEFAULT;
248   if (IsExpandedParamKnown(newParams[1]))
249     iIcon = pRuntime->ToInt32(newParams[1]);
250 
251   int iType = JSPLATFORM_ALERT_BUTTON_DEFAULT;
252   if (IsExpandedParamKnown(newParams[2]))
253     iType = pRuntime->ToInt32(newParams[2]);
254 
255   WideString swTitle;
256   if (IsExpandedParamKnown(newParams[3]))
257     swTitle = pRuntime->ToWideString(newParams[3]);
258   else
259     swTitle = JSGetStringFromID(JSMessage::kAlert);
260 
261   pRuntime->BeginBlock();
262   pFormFillEnv->KillFocusAnnot({});
263   v8::Local<v8::Value> ret = pRuntime->NewNumber(
264       pFormFillEnv->JS_appAlert(swMsg, swTitle, iType, iIcon));
265   pRuntime->EndBlock();
266 
267   return CJS_Result::Success(ret);
268 }
269 
beep(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)270 CJS_Result CJS_App::beep(CJS_Runtime* pRuntime,
271                          const std::vector<v8::Local<v8::Value>>& params) {
272   if (params.size() != 1)
273     return CJS_Result::Failure(JSMessage::kParamError);
274 
275   int type = JSPLATFORM_BEEP_DEFAULT;
276   if (IsExpandedParamKnown(params[0]))
277     type = pRuntime->ToInt32(params[0]);
278 
279   pRuntime->GetFormFillEnv()->JS_appBeep(type);
280   return CJS_Result::Success();
281 }
282 
findComponent(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)283 CJS_Result CJS_App::findComponent(
284     CJS_Runtime* pRuntime,
285     const std::vector<v8::Local<v8::Value>>& params) {
286   return CJS_Result::Success();
287 }
288 
popUpMenuEx(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)289 CJS_Result CJS_App::popUpMenuEx(
290     CJS_Runtime* pRuntime,
291     const std::vector<v8::Local<v8::Value>>& params) {
292   return CJS_Result::Failure(JSMessage::kNotSupportedError);
293 }
294 
get_fs(CJS_Runtime * pRuntime)295 CJS_Result CJS_App::get_fs(CJS_Runtime* pRuntime) {
296   return CJS_Result::Failure(JSMessage::kNotSupportedError);
297 }
298 
set_fs(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)299 CJS_Result CJS_App::set_fs(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
300   return CJS_Result::Failure(JSMessage::kNotSupportedError);
301 }
302 
setInterval(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)303 CJS_Result CJS_App::setInterval(
304     CJS_Runtime* pRuntime,
305     const std::vector<v8::Local<v8::Value>>& params) {
306   if (params.size() == 0 || params.size() > 2)
307     return CJS_Result::Failure(JSMessage::kParamError);
308 
309   WideString script = pRuntime->ToWideString(params[0]);
310   if (script.IsEmpty())
311     return CJS_Result::Failure(JSMessage::kInvalidInputError);
312 
313   uint32_t dwInterval = params.size() > 1 ? pRuntime->ToInt32(params[1]) : 1000;
314   auto timerRef = std::make_unique<GlobalTimer>(
315       this, pRuntime, GlobalTimer::Type::kRepeating, script, dwInterval, 0);
316   GlobalTimer* pTimerRef = timerRef.get();
317   m_Timers.insert(std::move(timerRef));
318 
319   v8::Local<v8::Object> pRetObj = pRuntime->NewFXJSBoundObject(
320       CJS_TimerObj::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
321   if (pRetObj.IsEmpty())
322     return CJS_Result::Failure(JSMessage::kBadObjectError);
323 
324   auto* pJS_TimerObj = static_cast<CJS_TimerObj*>(
325       CFXJS_Engine::GetObjectPrivate(pRuntime->GetIsolate(), pRetObj));
326 
327   pJS_TimerObj->SetTimer(pTimerRef);
328   return CJS_Result::Success(pRetObj);
329 }
330 
setTimeOut(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)331 CJS_Result CJS_App::setTimeOut(
332     CJS_Runtime* pRuntime,
333     const std::vector<v8::Local<v8::Value>>& params) {
334   if (params.size() == 0 || params.size() > 2)
335     return CJS_Result::Failure(JSMessage::kParamError);
336 
337   WideString script = pRuntime->ToWideString(params[0]);
338   if (script.IsEmpty())
339     return CJS_Result::Failure(JSMessage::kInvalidInputError);
340 
341   uint32_t dwTimeOut = params.size() > 1 ? pRuntime->ToInt32(params[1]) : 1000;
342   auto timerRef =
343       std::make_unique<GlobalTimer>(this, pRuntime, GlobalTimer::Type::kOneShot,
344                                     script, dwTimeOut, dwTimeOut);
345   GlobalTimer* pTimerRef = timerRef.get();
346   m_Timers.insert(std::move(timerRef));
347 
348   v8::Local<v8::Object> pRetObj = pRuntime->NewFXJSBoundObject(
349       CJS_TimerObj::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
350   if (pRetObj.IsEmpty())
351     return CJS_Result::Failure(JSMessage::kBadObjectError);
352 
353   auto* pJS_TimerObj = static_cast<CJS_TimerObj*>(
354       CFXJS_Engine::GetObjectPrivate(pRuntime->GetIsolate(), pRetObj));
355 
356   pJS_TimerObj->SetTimer(pTimerRef);
357   return CJS_Result::Success(pRetObj);
358 }
359 
clearTimeOut(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)360 CJS_Result CJS_App::clearTimeOut(
361     CJS_Runtime* pRuntime,
362     const std::vector<v8::Local<v8::Value>>& params) {
363   if (params.size() != 1)
364     return CJS_Result::Failure(JSMessage::kParamError);
365 
366   CJS_App::ClearTimerCommon(pRuntime, params[0]);
367   return CJS_Result::Success();
368 }
369 
clearInterval(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)370 CJS_Result CJS_App::clearInterval(
371     CJS_Runtime* pRuntime,
372     const std::vector<v8::Local<v8::Value>>& params) {
373   if (params.size() != 1)
374     return CJS_Result::Failure(JSMessage::kParamError);
375 
376   CJS_App::ClearTimerCommon(pRuntime, params[0]);
377   return CJS_Result::Success();
378 }
379 
ClearTimerCommon(CJS_Runtime * pRuntime,v8::Local<v8::Value> param)380 void CJS_App::ClearTimerCommon(CJS_Runtime* pRuntime,
381                                v8::Local<v8::Value> param) {
382   if (!param->IsObject())
383     return;
384 
385   v8::Local<v8::Object> pObj = pRuntime->ToObject(param);
386   auto pTimer = JSGetObject<CJS_TimerObj>(pRuntime->GetIsolate(), pObj);
387   if (!pTimer)
388     return;
389 
390   GlobalTimer::Cancel(pTimer->GetTimerID());
391 }
392 
execMenuItem(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)393 CJS_Result CJS_App::execMenuItem(
394     CJS_Runtime* pRuntime,
395     const std::vector<v8::Local<v8::Value>>& params) {
396   return CJS_Result::Failure(JSMessage::kNotSupportedError);
397 }
398 
TimerProc(GlobalTimer * pTimer)399 void CJS_App::TimerProc(GlobalTimer* pTimer) {
400   CJS_Runtime* pRuntime = pTimer->GetRuntime();
401   if (pRuntime && (!pTimer->IsOneShot() || pTimer->GetTimeOut() > 0))
402     RunJsScript(pRuntime, pTimer->GetJScript());
403 }
404 
CancelProc(GlobalTimer * pTimer)405 void CJS_App::CancelProc(GlobalTimer* pTimer) {
406   m_Timers.erase(fxcrt::MakeFakeUniquePtr(pTimer));
407 }
408 
RunJsScript(CJS_Runtime * pRuntime,const WideString & wsScript)409 void CJS_App::RunJsScript(CJS_Runtime* pRuntime, const WideString& wsScript) {
410   if (pRuntime->IsBlocking())
411     return;
412 
413   IJS_Runtime::ScopedEventContext pContext(pRuntime);
414   pContext->OnExternal_Exec();
415   pContext->RunScript(wsScript);
416 }
417 
goBack(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)418 CJS_Result CJS_App::goBack(CJS_Runtime* pRuntime,
419                            const std::vector<v8::Local<v8::Value>>& params) {
420   // Not supported, but do not return error.
421   return CJS_Result::Success();
422 }
423 
goForward(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)424 CJS_Result CJS_App::goForward(CJS_Runtime* pRuntime,
425                               const std::vector<v8::Local<v8::Value>>& params) {
426   // Not supported, but do not return error.
427   return CJS_Result::Success();
428 }
429 
mailMsg(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)430 CJS_Result CJS_App::mailMsg(CJS_Runtime* pRuntime,
431                             const std::vector<v8::Local<v8::Value>>& params) {
432   std::vector<v8::Local<v8::Value>> newParams = ExpandKeywordParams(
433       pRuntime, params, 6, "bUI", "cTo", "cCc", "cBcc", "cSubject", "cMsg");
434 
435   if (!IsExpandedParamKnown(newParams[0]))
436     return CJS_Result::Failure(JSMessage::kParamError);
437 
438   bool bUI = pRuntime->ToBoolean(newParams[0]);
439   WideString cTo;
440   if (IsExpandedParamKnown(newParams[1])) {
441     cTo = pRuntime->ToWideString(newParams[1]);
442   } else {
443     // cTo parameter required when UI not invoked.
444     if (!bUI)
445       return CJS_Result::Failure(JSMessage::kParamError);
446   }
447 
448   WideString cCc;
449   if (IsExpandedParamKnown(newParams[2]))
450     cCc = pRuntime->ToWideString(newParams[2]);
451 
452   WideString cBcc;
453   if (IsExpandedParamKnown(newParams[3]))
454     cBcc = pRuntime->ToWideString(newParams[3]);
455 
456   WideString cSubject;
457   if (IsExpandedParamKnown(newParams[4]))
458     cSubject = pRuntime->ToWideString(newParams[4]);
459 
460   WideString cMsg;
461   if (IsExpandedParamKnown(newParams[5]))
462     cMsg = pRuntime->ToWideString(newParams[5]);
463 
464   pRuntime->BeginBlock();
465   pRuntime->GetFormFillEnv()->JS_docmailForm(pdfium::span<const uint8_t>(), bUI,
466                                              cTo, cSubject, cCc, cBcc, cMsg);
467   pRuntime->EndBlock();
468   return CJS_Result::Success();
469 }
470 
launchURL(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)471 CJS_Result CJS_App::launchURL(CJS_Runtime* pRuntime,
472                               const std::vector<v8::Local<v8::Value>>& params) {
473   // Unsafe, not supported, but do not return error.
474   return CJS_Result::Success();
475 }
476 
get_runtime_highlight(CJS_Runtime * pRuntime)477 CJS_Result CJS_App::get_runtime_highlight(CJS_Runtime* pRuntime) {
478   return CJS_Result::Success(pRuntime->NewBoolean(m_bRuntimeHighLight));
479 }
480 
set_runtime_highlight(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)481 CJS_Result CJS_App::set_runtime_highlight(CJS_Runtime* pRuntime,
482                                           v8::Local<v8::Value> vp) {
483   m_bRuntimeHighLight = pRuntime->ToBoolean(vp);
484   return CJS_Result::Success();
485 }
486 
get_fullscreen(CJS_Runtime * pRuntime)487 CJS_Result CJS_App::get_fullscreen(CJS_Runtime* pRuntime) {
488   return CJS_Result::Failure(JSMessage::kNotSupportedError);
489 }
490 
set_fullscreen(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)491 CJS_Result CJS_App::set_fullscreen(CJS_Runtime* pRuntime,
492                                    v8::Local<v8::Value> vp) {
493   return CJS_Result::Failure(JSMessage::kNotSupportedError);
494 }
495 
popUpMenu(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)496 CJS_Result CJS_App::popUpMenu(CJS_Runtime* pRuntime,
497                               const std::vector<v8::Local<v8::Value>>& params) {
498   return CJS_Result::Failure(JSMessage::kNotSupportedError);
499 }
500 
browseForDoc(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)501 CJS_Result CJS_App::browseForDoc(
502     CJS_Runtime* pRuntime,
503     const std::vector<v8::Local<v8::Value>>& params) {
504   // Unsafe, not supported, but do not return an error.
505   return CJS_Result::Success();
506 }
507 
SysPathToPDFPath(const WideString & sOldPath)508 WideString CJS_App::SysPathToPDFPath(const WideString& sOldPath) {
509   WideString sRet = L"/";
510   for (const wchar_t& c : sOldPath) {
511     if (c != L':')
512       sRet += (c == L'\\') ? L'/' : c;
513   }
514   return sRet;
515 }
516 
newDoc(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)517 CJS_Result CJS_App::newDoc(CJS_Runtime* pRuntime,
518                            const std::vector<v8::Local<v8::Value>>& params) {
519   return CJS_Result::Failure(JSMessage::kNotSupportedError);
520 }
521 
openDoc(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)522 CJS_Result CJS_App::openDoc(CJS_Runtime* pRuntime,
523                             const std::vector<v8::Local<v8::Value>>& params) {
524   return CJS_Result::Failure(JSMessage::kNotSupportedError);
525 }
526 
response(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)527 CJS_Result CJS_App::response(CJS_Runtime* pRuntime,
528                              const std::vector<v8::Local<v8::Value>>& params) {
529   std::vector<v8::Local<v8::Value>> newParams =
530       ExpandKeywordParams(pRuntime, params, 5, "cQuestion", "cTitle",
531                           "cDefault", "bPassword", "cLabel");
532 
533   if (!IsExpandedParamKnown(newParams[0]))
534     return CJS_Result::Failure(JSMessage::kParamError);
535 
536   WideString swQuestion = pRuntime->ToWideString(newParams[0]);
537   WideString swTitle = L"PDF";
538   if (IsExpandedParamKnown(newParams[1]))
539     swTitle = pRuntime->ToWideString(newParams[1]);
540 
541   WideString swDefault;
542   if (IsExpandedParamKnown(newParams[2]))
543     swDefault = pRuntime->ToWideString(newParams[2]);
544 
545   bool bPassword = false;
546   if (IsExpandedParamKnown(newParams[3]))
547     bPassword = pRuntime->ToBoolean(newParams[3]);
548 
549   WideString swLabel;
550   if (IsExpandedParamKnown(newParams[4]))
551     swLabel = pRuntime->ToWideString(newParams[4]);
552 
553   constexpr int kMaxWideChars = 1024;
554   constexpr int kMaxBytes = kMaxWideChars * sizeof(uint16_t);
555   FixedZeroedDataVector<uint16_t> buffer(kMaxWideChars);
556   pdfium::span<uint16_t> buffer_span = buffer.writable_span();
557   int byte_length = pRuntime->GetFormFillEnv()->JS_appResponse(
558       swQuestion, swTitle, swDefault, swLabel, bPassword,
559       pdfium::as_writable_bytes(buffer_span));
560   if (byte_length < 0 || byte_length > kMaxBytes)
561     return CJS_Result::Failure(JSMessage::kParamTooLongError);
562 
563   buffer_span = buffer_span.first(
564       std::min<size_t>(kMaxWideChars, byte_length / sizeof(uint16_t)));
565   return CJS_Result::Success(pRuntime->NewString(
566       WideString::FromUTF16LE(buffer_span.data(), buffer_span.size())
567           .AsStringView()));
568 }
569 
get_media(CJS_Runtime * pRuntime)570 CJS_Result CJS_App::get_media(CJS_Runtime* pRuntime) {
571   return CJS_Result::Failure(JSMessage::kNotSupportedError);
572 }
573 
set_media(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)574 CJS_Result CJS_App::set_media(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
575   return CJS_Result::Failure(JSMessage::kNotSupportedError);
576 }
577 
execDialog(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)578 CJS_Result CJS_App::execDialog(
579     CJS_Runtime* pRuntime,
580     const std::vector<v8::Local<v8::Value>>& params) {
581   return CJS_Result::Success();
582 }
583