clang-format all pdfium code, again.
[pdfium.git] / fpdfsdk / src / javascript / app.cpp
1 // Copyright 2014 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 "../../../third_party/base/nonstd_unique_ptr.h"
8 #include "../../include/javascript/JavaScript.h"
9 #include "../../include/javascript/IJavaScript.h"
10 #include "../../include/javascript/JS_Define.h"
11 #include "../../include/javascript/JS_Object.h"
12 #include "../../include/javascript/JS_Value.h"
13 #include "../../include/javascript/app.h"
14 #include "../../include/javascript/JS_EventHandler.h"
15 #include "../../include/javascript/resource.h"
16 #include "../../include/javascript/JS_Context.h"
17 #include "../../include/javascript/JS_Runtime.h"
18 #include "../../include/javascript/Document.h"
19
20 static v8::Isolate* GetIsolate(IFXJS_Context* cc) {
21   CJS_Context* pContext = (CJS_Context*)cc;
22   ASSERT(pContext != NULL);
23
24   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
25   ASSERT(pRuntime != NULL);
26
27   return pRuntime->GetIsolate();
28 }
29
30 /* ---------------------------- TimerObj ---------------------------- */
31
32 BEGIN_JS_STATIC_CONST(CJS_TimerObj)
33 END_JS_STATIC_CONST()
34
35 BEGIN_JS_STATIC_PROP(CJS_TimerObj)
36 END_JS_STATIC_PROP()
37
38 BEGIN_JS_STATIC_METHOD(CJS_TimerObj)
39 END_JS_STATIC_METHOD()
40
41 IMPLEMENT_JS_CLASS(CJS_TimerObj, TimerObj)
42
43 TimerObj::TimerObj(CJS_Object* pJSObject)
44     : CJS_EmbedObj(pJSObject), m_pTimer(NULL) {}
45
46 TimerObj::~TimerObj() {}
47
48 void TimerObj::SetTimer(CJS_Timer* pTimer) {
49   m_pTimer = pTimer;
50 }
51
52 CJS_Timer* TimerObj::GetTimer() const {
53   return m_pTimer;
54 }
55
56 #define JS_STR_VIEWERTYPE_READER L"Reader"
57 #define JS_STR_VIEWERTYPE_STANDARD L"Exchange"
58 #define JS_STR_VIEWERVARIATION L"Full"
59 #define JS_STR_PLATFORM L"WIN"
60 #define JS_STR_LANGUANGE L"ENU"
61 #define JS_STR_VIEWERVERSION 8
62 #define JS_NUM_FORMSVERSION 7
63
64 #define JS_FILEPATH_MAXLEN 2000
65
66 /* ---------------------------- app ---------------------------- */
67
68 BEGIN_JS_STATIC_CONST(CJS_App)
69 END_JS_STATIC_CONST()
70
71 BEGIN_JS_STATIC_PROP(CJS_App)
72 JS_STATIC_PROP_ENTRY(activeDocs)
73 JS_STATIC_PROP_ENTRY(calculate)
74 JS_STATIC_PROP_ENTRY(formsVersion)
75 JS_STATIC_PROP_ENTRY(fs)
76 JS_STATIC_PROP_ENTRY(fullscreen)
77 JS_STATIC_PROP_ENTRY(language)
78 JS_STATIC_PROP_ENTRY(media)
79 JS_STATIC_PROP_ENTRY(platform)
80 JS_STATIC_PROP_ENTRY(runtimeHighlight)
81 JS_STATIC_PROP_ENTRY(viewerType)
82 JS_STATIC_PROP_ENTRY(viewerVariation)
83 JS_STATIC_PROP_ENTRY(viewerVersion)
84 END_JS_STATIC_PROP()
85
86 BEGIN_JS_STATIC_METHOD(CJS_App)
87 JS_STATIC_METHOD_ENTRY(alert)
88 JS_STATIC_METHOD_ENTRY(beep)
89 JS_STATIC_METHOD_ENTRY(browseForDoc)
90 JS_STATIC_METHOD_ENTRY(clearInterval)
91 JS_STATIC_METHOD_ENTRY(clearTimeOut)
92 JS_STATIC_METHOD_ENTRY(execDialog)
93 JS_STATIC_METHOD_ENTRY(execMenuItem)
94 JS_STATIC_METHOD_ENTRY(findComponent)
95 JS_STATIC_METHOD_ENTRY(goBack)
96 JS_STATIC_METHOD_ENTRY(goForward)
97 JS_STATIC_METHOD_ENTRY(launchURL)
98 JS_STATIC_METHOD_ENTRY(mailMsg)
99 JS_STATIC_METHOD_ENTRY(newFDF)
100 JS_STATIC_METHOD_ENTRY(newDoc)
101 JS_STATIC_METHOD_ENTRY(openDoc)
102 JS_STATIC_METHOD_ENTRY(openFDF)
103 JS_STATIC_METHOD_ENTRY(popUpMenuEx)
104 JS_STATIC_METHOD_ENTRY(popUpMenu)
105 JS_STATIC_METHOD_ENTRY(response)
106 JS_STATIC_METHOD_ENTRY(setInterval)
107 JS_STATIC_METHOD_ENTRY(setTimeOut)
108 END_JS_STATIC_METHOD()
109
110 IMPLEMENT_JS_CLASS(CJS_App, app)
111
112 app::app(CJS_Object* pJSObject)
113     : CJS_EmbedObj(pJSObject), m_bCalculate(true), m_bRuntimeHighLight(false) {}
114
115 app::~app(void) {
116   for (int i = 0, sz = m_aTimer.GetSize(); i < sz; i++)
117     delete m_aTimer[i];
118
119   m_aTimer.RemoveAll();
120 }
121
122 FX_BOOL app::activeDocs(IFXJS_Context* cc,
123                         CJS_PropValue& vp,
124                         CFX_WideString& sError) {
125   if (!vp.IsGetting())
126     return FALSE;
127
128   CJS_Context* pContext = (CJS_Context*)cc;
129   CPDFDoc_Environment* pApp = pContext->GetReaderApp();
130   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
131   CPDFSDK_Document* pCurDoc = pContext->GetReaderDocument();
132   CJS_Array aDocs(pRuntime->GetIsolate());
133   if (CPDFSDK_Document* pDoc = pApp->GetSDKDocument()) {
134     CJS_Document* pJSDocument = NULL;
135     if (pDoc == pCurDoc) {
136       JSFXObject pObj = JS_GetThisObj(*pRuntime);
137       if (JS_GetObjDefnID(pObj) == JS_GetObjDefnID(*pRuntime, L"Document"))
138         pJSDocument =
139             (CJS_Document*)JS_GetPrivate(pRuntime->GetIsolate(), pObj);
140     } else {
141       JSFXObject pObj = JS_NewFxDynamicObj(
142           *pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"Document"));
143       pJSDocument = (CJS_Document*)JS_GetPrivate(pRuntime->GetIsolate(), pObj);
144       ASSERT(pJSDocument != NULL);
145     }
146     aDocs.SetElement(0, CJS_Value(pRuntime->GetIsolate(), pJSDocument));
147   }
148   if (aDocs.GetLength() > 0)
149     vp << aDocs;
150   else
151     vp.SetNull();
152
153   return TRUE;
154 }
155
156 FX_BOOL app::calculate(IFXJS_Context* cc,
157                        CJS_PropValue& vp,
158                        CFX_WideString& sError) {
159   if (vp.IsSetting()) {
160     bool bVP;
161     vp >> bVP;
162     m_bCalculate = (FX_BOOL)bVP;
163
164     CJS_Context* pContext = (CJS_Context*)cc;
165     CPDFDoc_Environment* pApp = pContext->GetReaderApp();
166     CJS_Runtime* pRuntime = pContext->GetJSRuntime();
167     CJS_Array aDocs(pRuntime->GetIsolate());
168     if (CPDFSDK_Document* pDoc = pApp->GetSDKDocument())
169       pDoc->GetInterForm()->EnableCalculate((FX_BOOL)m_bCalculate);
170   } else {
171     vp << (bool)m_bCalculate;
172   }
173   return TRUE;
174 }
175
176 FX_BOOL app::formsVersion(IFXJS_Context* cc,
177                           CJS_PropValue& vp,
178                           CFX_WideString& sError) {
179   if (vp.IsGetting()) {
180     vp << JS_NUM_FORMSVERSION;
181     return TRUE;
182   }
183
184   return FALSE;
185 }
186
187 FX_BOOL app::viewerType(IFXJS_Context* cc,
188                         CJS_PropValue& vp,
189                         CFX_WideString& sError) {
190   if (vp.IsGetting()) {
191     vp << L"unknown";
192     return TRUE;
193   }
194
195   return FALSE;
196 }
197
198 FX_BOOL app::viewerVariation(IFXJS_Context* cc,
199                              CJS_PropValue& vp,
200                              CFX_WideString& sError) {
201   if (vp.IsGetting()) {
202     vp << JS_STR_VIEWERVARIATION;
203     return TRUE;
204   }
205
206   return FALSE;
207 }
208
209 FX_BOOL app::viewerVersion(IFXJS_Context* cc,
210                            CJS_PropValue& vp,
211                            CFX_WideString& sError) {
212   if (vp.IsGetting()) {
213     vp << JS_STR_VIEWERVERSION;
214     return TRUE;
215   }
216
217   return FALSE;
218 }
219
220 FX_BOOL app::platform(IFXJS_Context* cc,
221                       CJS_PropValue& vp,
222                       CFX_WideString& sError) {
223   if (vp.IsGetting()) {
224     vp << JS_STR_PLATFORM;
225     return TRUE;
226   }
227
228   return FALSE;
229 }
230
231 FX_BOOL app::language(IFXJS_Context* cc,
232                       CJS_PropValue& vp,
233                       CFX_WideString& sError) {
234   if (vp.IsGetting()) {
235     vp << JS_STR_LANGUANGE;
236     return TRUE;
237   }
238
239   return FALSE;
240 }
241
242 // creates a new fdf object that contains no data
243 // comment: need reader support
244 // note:
245 // CFDF_Document * CPDFDoc_Environment::NewFDF();
246 FX_BOOL app::newFDF(IFXJS_Context* cc,
247                     const CJS_Parameters& params,
248                     CJS_Value& vRet,
249                     CFX_WideString& sError) {
250   return TRUE;
251 }
252 // opens a specified pdf document and returns its document object
253 // comment:need reader support
254 // note: as defined in js reference, the proto of this function's fourth
255 // parmeters, how old an fdf document while do not show it.
256 // CFDF_Document * CPDFDoc_Environment::OpenFDF(string strPath,bool bUserConv);
257
258 FX_BOOL app::openFDF(IFXJS_Context* cc,
259                      const CJS_Parameters& params,
260                      CJS_Value& vRet,
261                      CFX_WideString& sError) {
262   return TRUE;
263 }
264
265 FX_BOOL app::alert(IFXJS_Context* cc,
266                    const CJS_Parameters& params,
267                    CJS_Value& vRet,
268                    CFX_WideString& sError) {
269   int iSize = params.size();
270   if (iSize < 1)
271     return FALSE;
272
273   CFX_WideString swMsg = L"";
274   CFX_WideString swTitle = L"";
275   int iIcon = 0;
276   int iType = 0;
277
278   v8::Isolate* isolate = GetIsolate(cc);
279
280   if (iSize == 1) {
281     if (params[0].GetType() == VT_object) {
282       JSObject pObj = params[0].ToV8Object();
283       {
284         v8::Local<v8::Value> pValue =
285             JS_GetObjectElement(isolate, pObj, L"cMsg");
286         swMsg = CJS_Value(isolate, pValue, VT_unknown).ToCFXWideString();
287
288         pValue = JS_GetObjectElement(isolate, pObj, L"cTitle");
289         swTitle = CJS_Value(isolate, pValue, VT_unknown).ToCFXWideString();
290
291         pValue = JS_GetObjectElement(isolate, pObj, L"nIcon");
292         iIcon = CJS_Value(isolate, pValue, VT_unknown).ToInt();
293
294         pValue = JS_GetObjectElement(isolate, pObj, L"nType");
295         iType = CJS_Value(isolate, pValue, VT_unknown).ToInt();
296       }
297
298       if (swMsg == L"") {
299         CJS_Array carray(isolate);
300         if (params[0].ConvertToArray(carray)) {
301           int iLenth = carray.GetLength();
302           CJS_Value* pValue = new CJS_Value(isolate);
303           //                                    if (iLenth == 1)
304           //                                            pValue = new
305           // CJS_Value(isolate);
306           //                                    else if (iLenth > 1)
307           //                                            pValue = new
308           // CJS_Value[iLenth];
309
310           for (int i = 0; i < iLenth; i++) {
311             carray.GetElement(i, *pValue);
312             swMsg += (*pValue).ToCFXWideString();
313             if (i < iLenth - 1)
314               swMsg += L",  ";
315           }
316
317           delete pValue;
318         }
319       }
320
321       if (swTitle == L"")
322         swTitle = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSALERT);
323     } else if (params[0].GetType() == VT_boolean) {
324       FX_BOOL bGet = params[0].ToBool();
325       if (bGet)
326         swMsg = L"true";
327       else
328         swMsg = L"false";
329
330       swTitle = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSALERT);
331     } else {
332       swMsg = params[0].ToCFXWideString();
333       swTitle = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSALERT);
334     }
335   } else {
336     if (params[0].GetType() == VT_boolean) {
337       FX_BOOL bGet = params[0].ToBool();
338       if (bGet)
339         swMsg = L"true";
340       else
341         swMsg = L"false";
342     } else {
343       swMsg = params[0].ToCFXWideString();
344     }
345     swTitle = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSALERT);
346
347     for (int i = 1; i < iSize; i++) {
348       if (i == 1)
349         iIcon = params[i].ToInt();
350       if (i == 2)
351         iType = params[i].ToInt();
352       if (i == 3)
353         swTitle = params[i].ToCFXWideString();
354     }
355   }
356
357   CJS_Context* pContext = (CJS_Context*)cc;
358   ASSERT(pContext != NULL);
359   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
360   ASSERT(pRuntime != NULL);
361   pRuntime->BeginBlock();
362   vRet = MsgBox(pRuntime->GetReaderApp(), JSGetPageView(cc), swMsg.c_str(),
363                 swTitle.c_str(), iType, iIcon);
364   pRuntime->EndBlock();
365
366   return TRUE;
367 }
368
369 FX_BOOL app::beep(IFXJS_Context* cc,
370                   const CJS_Parameters& params,
371                   CJS_Value& vRet,
372                   CFX_WideString& sError) {
373   if (params.size() == 1) {
374     CJS_Context* pContext = (CJS_Context*)cc;
375     CJS_Runtime* pRuntime = pContext->GetJSRuntime();
376     CPDFDoc_Environment* pEnv = pRuntime->GetReaderApp();
377     pEnv->JS_appBeep(params[0].ToInt());
378     return TRUE;
379   }
380
381   sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPARAMERROR);
382   return FALSE;
383 }
384
385 FX_BOOL app::findComponent(IFXJS_Context* cc,
386                            const CJS_Parameters& params,
387                            CJS_Value& vRet,
388                            CFX_WideString& sError) {
389   return TRUE;
390 }
391
392 FX_BOOL app::popUpMenuEx(IFXJS_Context* cc,
393                          const CJS_Parameters& params,
394                          CJS_Value& vRet,
395                          CFX_WideString& sError) {
396   return FALSE;
397 }
398
399 FX_BOOL app::fs(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError) {
400   return FALSE;
401 }
402
403 FX_BOOL app::setInterval(IFXJS_Context* cc,
404                          const CJS_Parameters& params,
405                          CJS_Value& vRet,
406                          CFX_WideString& sError) {
407   CJS_Context* pContext = (CJS_Context*)cc;
408   if (params.size() > 2 || params.size() == 0) {
409     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
410     return FALSE;
411   }
412
413   CFX_WideString script = params.size() > 0 ? params[0].ToCFXWideString() : L"";
414   if (script.IsEmpty()) {
415     sError = JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE);
416     return TRUE;
417   }
418
419   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
420   FX_DWORD dwInterval = params.size() > 1 ? params[1].ToInt() : 1000;
421
422   CPDFDoc_Environment* pApp = pRuntime->GetReaderApp();
423   ASSERT(pApp);
424   CJS_Timer* pTimer = new CJS_Timer(this, pApp);
425   m_aTimer.Add(pTimer);
426
427   pTimer->SetType(0);
428   pTimer->SetRuntime(pRuntime);
429   pTimer->SetJScript(script);
430   pTimer->SetTimeOut(0);
431   //    pTimer->SetStartTime(GetTickCount());
432   pTimer->SetJSTimer(dwInterval);
433
434   JSFXObject pRetObj = JS_NewFxDynamicObj(
435       *pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"TimerObj"));
436
437   CJS_TimerObj* pJS_TimerObj =
438       (CJS_TimerObj*)JS_GetPrivate(pRuntime->GetIsolate(), pRetObj);
439   ASSERT(pJS_TimerObj != NULL);
440
441   TimerObj* pTimerObj = (TimerObj*)pJS_TimerObj->GetEmbedObject();
442   ASSERT(pTimerObj != NULL);
443
444   pTimerObj->SetTimer(pTimer);
445
446   vRet = pRetObj;
447
448   return TRUE;
449 }
450
451 FX_BOOL app::setTimeOut(IFXJS_Context* cc,
452                         const CJS_Parameters& params,
453                         CJS_Value& vRet,
454                         CFX_WideString& sError) {
455   if (params.size() > 2 || params.size() == 0) {
456     sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPARAMERROR);
457     return FALSE;
458   }
459
460   CJS_Context* pContext = (CJS_Context*)cc;
461   ASSERT(pContext != NULL);
462   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
463   ASSERT(pRuntime != NULL);
464
465   CFX_WideString script = params.size() > 0 ? params[0].ToCFXWideString() : L"";
466   if (script.IsEmpty()) {
467     sError =
468         JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSAFNUMBER_KEYSTROKE);
469     return TRUE;
470   }
471
472   FX_DWORD dwTimeOut = params.size() > 1 ? params[1].ToInt() : 1000;
473
474   CPDFDoc_Environment* pApp = pRuntime->GetReaderApp();
475   ASSERT(pApp);
476
477   CJS_Timer* pTimer = new CJS_Timer(this, pApp);
478   m_aTimer.Add(pTimer);
479
480   pTimer->SetType(1);
481   pTimer->SetRuntime(pRuntime);
482   pTimer->SetJScript(script);
483   pTimer->SetTimeOut(dwTimeOut);
484   pTimer->SetJSTimer(dwTimeOut);
485
486   JSFXObject pRetObj = JS_NewFxDynamicObj(
487       *pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"TimerObj"));
488
489   CJS_TimerObj* pJS_TimerObj =
490       (CJS_TimerObj*)JS_GetPrivate(pRuntime->GetIsolate(), pRetObj);
491   ASSERT(pJS_TimerObj != NULL);
492
493   TimerObj* pTimerObj = (TimerObj*)pJS_TimerObj->GetEmbedObject();
494   ASSERT(pTimerObj != NULL);
495
496   pTimerObj->SetTimer(pTimer);
497
498   vRet = pRetObj;
499
500   return TRUE;
501 }
502
503 FX_BOOL app::clearTimeOut(IFXJS_Context* cc,
504                           const CJS_Parameters& params,
505                           CJS_Value& vRet,
506                           CFX_WideString& sError) {
507   CJS_Context* pContext = (CJS_Context*)cc;
508   ASSERT(pContext != NULL);
509   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
510   ASSERT(pRuntime != NULL);
511
512   if (params.size() != 1) {
513     sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPARAMERROR);
514     return FALSE;
515   }
516
517   if (params[0].GetType() == VT_fxobject) {
518     JSFXObject pObj = params[0].ToV8Object();
519     {
520       if (JS_GetObjDefnID(pObj) == JS_GetObjDefnID(*pRuntime, L"TimerObj")) {
521         if (CJS_Object* pJSObj = params[0].ToCJSObject()) {
522           if (TimerObj* pTimerObj = (TimerObj*)pJSObj->GetEmbedObject()) {
523             if (CJS_Timer* pTimer = pTimerObj->GetTimer()) {
524               pTimer->KillJSTimer();
525
526               for (int i = 0, sz = m_aTimer.GetSize(); i < sz; i++) {
527                 if (m_aTimer[i] == pTimer) {
528                   m_aTimer.RemoveAt(i);
529                   break;
530                 }
531               }
532
533               delete pTimer;
534               pTimerObj->SetTimer(NULL);
535             }
536           }
537         }
538       }
539     }
540   }
541
542   return TRUE;
543 }
544
545 FX_BOOL app::clearInterval(IFXJS_Context* cc,
546                            const CJS_Parameters& params,
547                            CJS_Value& vRet,
548                            CFX_WideString& sError) {
549   CJS_Context* pContext = (CJS_Context*)cc;
550   ASSERT(pContext != NULL);
551   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
552   ASSERT(pRuntime != NULL);
553
554   if (params.size() != 1) {
555     sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPARAMERROR);
556     return FALSE;
557   }
558
559   if (params[0].GetType() == VT_fxobject) {
560     JSFXObject pObj = params[0].ToV8Object();
561     {
562       if (JS_GetObjDefnID(pObj) == JS_GetObjDefnID(*pRuntime, L"TimerObj")) {
563         if (CJS_Object* pJSObj = params[0].ToCJSObject()) {
564           if (TimerObj* pTimerObj = (TimerObj*)pJSObj->GetEmbedObject()) {
565             if (CJS_Timer* pTimer = pTimerObj->GetTimer()) {
566               pTimer->KillJSTimer();
567
568               for (int i = 0, sz = m_aTimer.GetSize(); i < sz; i++) {
569                 if (m_aTimer[i] == pTimer) {
570                   m_aTimer.RemoveAt(i);
571                   break;
572                 }
573               }
574
575               delete pTimer;
576               pTimerObj->SetTimer(NULL);
577             }
578           }
579         }
580       }
581     }
582   }
583
584   return TRUE;
585 }
586
587 FX_BOOL app::execMenuItem(IFXJS_Context* cc,
588                           const CJS_Parameters& params,
589                           CJS_Value& vRet,
590                           CFX_WideString& sError) {
591   return FALSE;
592 }
593
594 void app::TimerProc(CJS_Timer* pTimer) {
595   ASSERT(pTimer != NULL);
596
597   switch (pTimer->GetType()) {
598     case 0:  // interval
599       RunJsScript(pTimer->GetRuntime(), pTimer->GetJScript());
600       break;
601     case 1:
602       if (pTimer->GetTimeOut() > 0) {
603         RunJsScript(pTimer->GetRuntime(), pTimer->GetJScript());
604         pTimer->KillJSTimer();
605       }
606       break;
607   }
608 }
609
610 void app::RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript) {
611   ASSERT(pRuntime != NULL);
612
613   if (!pRuntime->IsBlocking()) {
614     IFXJS_Context* pContext = pRuntime->NewContext();
615     ASSERT(pContext != NULL);
616     pContext->OnExternal_Exec();
617     CFX_WideString wtInfo;
618     pContext->RunScript(wsScript, wtInfo);
619     pRuntime->ReleaseContext(pContext);
620   }
621 }
622
623 FX_BOOL app::goBack(IFXJS_Context* cc,
624                     const CJS_Parameters& params,
625                     CJS_Value& vRet,
626                     CFX_WideString& sError) {
627   // Not supported.
628   return TRUE;
629 }
630
631 FX_BOOL app::goForward(IFXJS_Context* cc,
632                        const CJS_Parameters& params,
633                        CJS_Value& vRet,
634                        CFX_WideString& sError) {
635   // Not supported.
636   return TRUE;
637 }
638
639 FX_BOOL app::mailMsg(IFXJS_Context* cc,
640                      const CJS_Parameters& params,
641                      CJS_Value& vRet,
642                      CFX_WideString& sError) {
643   CJS_Context* pContext = (CJS_Context*)cc;
644   v8::Isolate* isolate = GetIsolate(cc);
645
646   FX_BOOL bUI = TRUE;
647   CFX_WideString cTo = L"";
648   CFX_WideString cCc = L"";
649   CFX_WideString cBcc = L"";
650   CFX_WideString cSubject = L"";
651   CFX_WideString cMsg = L"";
652
653   if (params.size() < 1)
654     return FALSE;
655
656   if (params[0].GetType() == VT_object) {
657     JSObject pObj = params[0].ToV8Object();
658
659     v8::Local<v8::Value> pValue = JS_GetObjectElement(isolate, pObj, L"bUI");
660     bUI = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToBool();
661
662     pValue = JS_GetObjectElement(isolate, pObj, L"cTo");
663     cTo = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
664
665     pValue = JS_GetObjectElement(isolate, pObj, L"cCc");
666     cCc = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
667
668     pValue = JS_GetObjectElement(isolate, pObj, L"cBcc");
669     cBcc = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
670
671     pValue = JS_GetObjectElement(isolate, pObj, L"cSubject");
672     cSubject =
673         CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
674
675     pValue = JS_GetObjectElement(isolate, pObj, L"cMsg");
676     cMsg = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
677   } else {
678     if (params.size() < 2)
679       return FALSE;
680
681     bUI = params[0].ToBool();
682     cTo = params[1].ToCFXWideString();
683
684     if (params.size() >= 3)
685       cCc = params[2].ToCFXWideString();
686     if (params.size() >= 4)
687       cBcc = params[3].ToCFXWideString();
688     if (params.size() >= 5)
689       cSubject = params[4].ToCFXWideString();
690     if (params.size() >= 6)
691       cMsg = params[5].ToCFXWideString();
692   }
693
694   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
695   ASSERT(pRuntime != NULL);
696
697   CPDFDoc_Environment* pApp = pContext->GetReaderApp();
698   ASSERT(pApp != NULL);
699
700   pRuntime->BeginBlock();
701   pApp->JS_docmailForm(NULL, 0, bUI, cTo.c_str(), cSubject.c_str(), cCc.c_str(),
702                        cBcc.c_str(), cMsg.c_str());
703   pRuntime->EndBlock();
704
705   return FALSE;
706 }
707
708 FX_BOOL app::launchURL(IFXJS_Context* cc,
709                        const CJS_Parameters& params,
710                        CJS_Value& vRet,
711                        CFX_WideString& sError) {
712   // Unsafe, not supported.
713   return TRUE;
714 }
715
716 FX_BOOL app::runtimeHighlight(IFXJS_Context* cc,
717                               CJS_PropValue& vp,
718                               CFX_WideString& sError) {
719   if (vp.IsSetting()) {
720     vp >> m_bRuntimeHighLight;
721   } else {
722     vp << m_bRuntimeHighLight;
723   }
724
725   return TRUE;
726 }
727
728 FX_BOOL app::fullscreen(IFXJS_Context* cc,
729                         CJS_PropValue& vp,
730                         CFX_WideString& sError) {
731   return FALSE;
732 }
733
734 FX_BOOL app::popUpMenu(IFXJS_Context* cc,
735                        const CJS_Parameters& params,
736                        CJS_Value& vRet,
737                        CFX_WideString& sError) {
738   return FALSE;
739 }
740
741 FX_BOOL app::browseForDoc(IFXJS_Context* cc,
742                           const CJS_Parameters& params,
743                           CJS_Value& vRet,
744                           CFX_WideString& sError) {
745   // Unsafe, not supported.
746   return TRUE;
747 }
748
749 CFX_WideString app::SysPathToPDFPath(const CFX_WideString& sOldPath) {
750   CFX_WideString sRet = L"/";
751
752   for (int i = 0, sz = sOldPath.GetLength(); i < sz; i++) {
753     wchar_t c = sOldPath.GetAt(i);
754     if (c == L':') {
755     } else {
756       if (c == L'\\') {
757         sRet += L"/";
758       } else {
759         sRet += c;
760       }
761     }
762   }
763
764   return sRet;
765 }
766
767 FX_BOOL app::newDoc(IFXJS_Context* cc,
768                     const CJS_Parameters& params,
769                     CJS_Value& vRet,
770                     CFX_WideString& sError) {
771   return FALSE;
772 }
773
774 FX_BOOL app::openDoc(IFXJS_Context* cc,
775                      const CJS_Parameters& params,
776                      CJS_Value& vRet,
777                      CFX_WideString& sError) {
778   return FALSE;
779 }
780
781 FX_BOOL app::response(IFXJS_Context* cc,
782                       const CJS_Parameters& params,
783                       CJS_Value& vRet,
784                       CFX_WideString& sError) {
785   CFX_WideString swQuestion = L"";
786   CFX_WideString swLabel = L"";
787   CFX_WideString swTitle = L"PDF";
788   CFX_WideString swDefault = L"";
789   bool bPassWord = false;
790
791   v8::Isolate* isolate = GetIsolate(cc);
792
793   int iLength = params.size();
794   if (iLength > 0 && params[0].GetType() == VT_object) {
795     JSObject pObj = params[0].ToV8Object();
796     v8::Local<v8::Value> pValue =
797         JS_GetObjectElement(isolate, pObj, L"cQuestion");
798     swQuestion =
799         CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
800
801     pValue = JS_GetObjectElement(isolate, pObj, L"cTitle");
802     swTitle =
803         CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
804
805     pValue = JS_GetObjectElement(isolate, pObj, L"cDefault");
806     swDefault =
807         CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
808
809     pValue = JS_GetObjectElement(isolate, pObj, L"cLabel");
810     swLabel =
811         CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
812
813     pValue = JS_GetObjectElement(isolate, pObj, L"bPassword");
814     bPassWord = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToBool();
815   } else {
816     switch (iLength) {
817       case 5:
818         swLabel = params[4].ToCFXWideString();
819       // FALLTHROUGH
820       case 4:
821         bPassWord = params[3].ToBool();
822       // FALLTHROUGH
823       case 3:
824         swDefault = params[2].ToCFXWideString();
825       // FALLTHROUGH
826       case 2:
827         swTitle = params[1].ToCFXWideString();
828       // FALLTHROUGH
829       case 1:
830         swQuestion = params[0].ToCFXWideString();
831       // FALLTHROUGH
832       default:
833         break;
834     }
835   }
836
837   CJS_Context* pContext = (CJS_Context*)cc;
838   ASSERT(pContext != NULL);
839
840   CPDFDoc_Environment* pApp = pContext->GetReaderApp();
841   ASSERT(pApp != NULL);
842
843   const int MAX_INPUT_BYTES = 2048;
844   nonstd::unique_ptr<char[]> pBuff(new char[MAX_INPUT_BYTES + 2]);
845   memset(pBuff.get(), 0, MAX_INPUT_BYTES + 2);
846   int nLengthBytes = pApp->JS_appResponse(
847       swQuestion.c_str(), swTitle.c_str(), swDefault.c_str(), swLabel.c_str(),
848       bPassWord, pBuff.get(), MAX_INPUT_BYTES);
849   if (nLengthBytes <= 0) {
850     vRet.SetNull();
851     return FALSE;
852   }
853   nLengthBytes = std::min(nLengthBytes, MAX_INPUT_BYTES);
854
855   CFX_WideString ret_string = CFX_WideString::FromUTF16LE(
856       (unsigned short*)pBuff.get(), nLengthBytes / sizeof(unsigned short));
857   vRet = ret_string.c_str();
858   return TRUE;
859 }
860
861 FX_BOOL app::media(IFXJS_Context* cc,
862                    CJS_PropValue& vp,
863                    CFX_WideString& sError) {
864   return FALSE;
865 }
866
867 FX_BOOL app::execDialog(IFXJS_Context* cc,
868                         const CJS_Parameters& params,
869                         CJS_Value& vRet,
870                         CFX_WideString& sError) {
871   return TRUE;
872 }