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