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