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