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