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
20static 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
33BEGIN_JS_STATIC_CONST(CJS_TimerObj)
34END_JS_STATIC_CONST()
35
36BEGIN_JS_STATIC_PROP(CJS_TimerObj)
37END_JS_STATIC_PROP()
38
39BEGIN_JS_STATIC_METHOD(CJS_TimerObj)
40END_JS_STATIC_METHOD()
41
42IMPLEMENT_JS_CLASS(CJS_TimerObj, TimerObj)
43
44TimerObj::TimerObj(CJS_Object* pJSObject)
45: CJS_EmbedObj(pJSObject),
46m_pTimer(NULL)
47{
48
49}
50
51TimerObj::~TimerObj()
52{
53}
54
55void TimerObj::SetTimer(CJS_Timer* pTimer)
56{
57	m_pTimer = pTimer;
58}
59
60CJS_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
77BEGIN_JS_STATIC_CONST(CJS_App)
78END_JS_STATIC_CONST()
79
80BEGIN_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)
93END_JS_STATIC_PROP()
94
95BEGIN_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)
117END_JS_STATIC_METHOD()
118
119IMPLEMENT_JS_CLASS(CJS_App,app)
120
121app::app(CJS_Object * pJSObject) : CJS_EmbedObj(pJSObject) ,
122	m_bCalculate(true),
123	m_bRuntimeHighLight(false)
124//	m_pMenuHead(NULL)
125{
126}
127
128app::~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
136FX_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
194FX_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
227FX_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
238FX_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
249FX_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
260FX_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
271FX_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
282FX_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();
297FX_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
306FX_BOOL app::openFDF(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
307{
308	return TRUE;
309}
310
311FX_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::Local<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.c_str(), swTitle.c_str(), iType, iIcon);
420	pRuntime->EndBlock();
421
422	return TRUE;
423}
424
425
426FX_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
441FX_BOOL app::findComponent(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
442{
443	return TRUE;
444}
445
446FX_BOOL app::popUpMenuEx(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
447{
448	return FALSE;
449}
450
451FX_BOOL app::fs(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
452{
453	return FALSE;
454}
455
456FX_BOOL app::setInterval(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
457{
458	CJS_Context* pContext = (CJS_Context*)cc;
459	if (params.size() > 2 || params.size() == 0)
460	{
461		sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
462		return FALSE;
463	}
464
465	CFX_WideString script = params.size() > 0 ?  params[0].ToCFXWideString() : L"";
466	if (script.IsEmpty())
467	{
468		sError = JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE);
469		return TRUE;
470	}
471
472	CJS_Runtime* pRuntime = pContext->GetJSRuntime();
473	FX_DWORD dwInterval = params.size() > 1 ? params[1].ToInt() : 1000;
474
475	CPDFDoc_Environment* pApp = pRuntime->GetReaderApp();
476	ASSERT(pApp);
477	CJS_Timer* pTimer = new CJS_Timer(this, pApp);
478	m_aTimer.Add(pTimer);
479
480	pTimer->SetType(0);
481	pTimer->SetRuntime(pRuntime);
482	pTimer->SetJScript(script);
483	pTimer->SetTimeOut(0);
484//	pTimer->SetStartTime(GetTickCount());
485	pTimer->SetJSTimer(dwInterval);
486
487	JSFXObject pRetObj = JS_NewFxDynamicObj(*pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"TimerObj"));
488
489	CJS_TimerObj* pJS_TimerObj = (CJS_TimerObj*)JS_GetPrivate(pRuntime->GetIsolate(),pRetObj);
490	ASSERT(pJS_TimerObj != NULL);
491
492	TimerObj* pTimerObj = (TimerObj*)pJS_TimerObj->GetEmbedObject();
493	ASSERT(pTimerObj != NULL);
494
495	pTimerObj->SetTimer(pTimer);
496
497	vRet = pRetObj;
498
499	return TRUE;
500}
501
502FX_BOOL app::setTimeOut(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
503{
504	if (params.size() > 2 || params.size() == 0)
505	{
506		sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPARAMERROR);
507		return FALSE;
508	}
509
510	CJS_Context* pContext = (CJS_Context*)cc;
511	ASSERT(pContext != NULL);
512	CJS_Runtime* pRuntime = pContext->GetJSRuntime();
513	ASSERT(pRuntime != NULL);
514
515	CFX_WideString script = params.size() > 0 ? params[0].ToCFXWideString() : L"";
516	if (script.IsEmpty())
517	{
518		sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSAFNUMBER_KEYSTROKE);
519		return TRUE;
520	}
521
522	FX_DWORD dwTimeOut = params.size() > 1 ? params[1].ToInt() : 1000;
523
524	CPDFDoc_Environment* pApp = pRuntime->GetReaderApp();
525	ASSERT(pApp);
526
527	CJS_Timer* pTimer = new CJS_Timer(this, pApp);
528	m_aTimer.Add(pTimer);
529
530	pTimer->SetType(1);
531	pTimer->SetRuntime(pRuntime);
532	pTimer->SetJScript(script);
533	pTimer->SetTimeOut(dwTimeOut);
534	pTimer->SetJSTimer(dwTimeOut);
535
536	JSFXObject pRetObj = JS_NewFxDynamicObj(*pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"TimerObj"));
537
538	CJS_TimerObj* pJS_TimerObj = (CJS_TimerObj*)JS_GetPrivate(pRuntime->GetIsolate(),pRetObj);
539	ASSERT(pJS_TimerObj != NULL);
540
541	TimerObj* pTimerObj = (TimerObj*)pJS_TimerObj->GetEmbedObject();
542	ASSERT(pTimerObj != NULL);
543
544	pTimerObj->SetTimer(pTimer);
545
546	vRet = pRetObj;
547
548	return TRUE;
549}
550
551FX_BOOL app::clearTimeOut(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
552{
553	CJS_Context* pContext = (CJS_Context*)cc;
554	ASSERT(pContext != NULL);
555	CJS_Runtime* pRuntime = pContext->GetJSRuntime();
556	ASSERT(pRuntime != NULL);
557
558	if (params.size() != 1)
559	{
560		sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPARAMERROR);
561		return FALSE;
562	}
563
564	if (params[0].GetType() == VT_fxobject)
565	{
566		JSFXObject pObj = params[0].ToV8Object();
567		{
568			if (JS_GetObjDefnID(pObj) == JS_GetObjDefnID(*pRuntime, L"TimerObj"))
569			{
570				if (CJS_Object* pJSObj = params[0].ToCJSObject())
571				{
572					if (TimerObj* pTimerObj = (TimerObj*)pJSObj->GetEmbedObject())
573					{
574						if (CJS_Timer* pTimer = pTimerObj->GetTimer())
575						{
576							pTimer->KillJSTimer();
577
578							for (int i=0,sz=m_aTimer.GetSize(); i<sz; i++)
579							{
580								if (m_aTimer[i] == pTimer)
581								{
582									m_aTimer.RemoveAt(i);
583									break;
584								}
585							}
586
587							delete pTimer;
588							pTimerObj->SetTimer(NULL);
589						}
590					}
591				}
592			}
593		}
594	}
595
596	return TRUE;
597}
598
599FX_BOOL app::clearInterval(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
600{
601	CJS_Context* pContext = (CJS_Context*)cc;
602	ASSERT(pContext != NULL);
603	CJS_Runtime* pRuntime = pContext->GetJSRuntime();
604	ASSERT(pRuntime != NULL);
605
606	if (params.size() != 1)
607	{
608		sError = JSGetStringFromID((CJS_Context*)cc, IDS_STRING_JSPARAMERROR);
609		return FALSE;
610	}
611
612	if (params[0].GetType() == VT_fxobject)
613	{
614		JSFXObject pObj = params[0].ToV8Object();
615		{
616			if (JS_GetObjDefnID(pObj) == JS_GetObjDefnID(*pRuntime, L"TimerObj"))
617			{
618				if (CJS_Object* pJSObj = params[0].ToCJSObject())
619				{
620					if (TimerObj* pTimerObj = (TimerObj*)pJSObj->GetEmbedObject())
621					{
622						if (CJS_Timer* pTimer = pTimerObj->GetTimer())
623						{
624							pTimer->KillJSTimer();
625
626							for (int i=0,sz=m_aTimer.GetSize(); i<sz; i++)
627							{
628								if (m_aTimer[i] == pTimer)
629								{
630									m_aTimer.RemoveAt(i);
631									break;
632								}
633							}
634
635							delete pTimer;
636							pTimerObj->SetTimer(NULL);
637						}
638					}
639				}
640			}
641		}
642	}
643
644	return TRUE;
645}
646
647FX_BOOL app::execMenuItem(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
648{
649	return FALSE;
650}
651
652void app::TimerProc(CJS_Timer* pTimer)
653{
654	ASSERT(pTimer != NULL);
655
656	switch (pTimer->GetType())
657	{
658	case 0: //interval
659		RunJsScript(pTimer->GetRuntime(), pTimer->GetJScript());
660		break;
661	case 1:
662		if (pTimer->GetTimeOut() > 0)
663		{
664			RunJsScript(pTimer->GetRuntime(), pTimer->GetJScript());
665			pTimer->KillJSTimer();
666		}
667		break;
668	}
669
670}
671
672void app::RunJsScript(CJS_Runtime* pRuntime,const CFX_WideString& wsScript)
673{
674	ASSERT(pRuntime != NULL);
675
676	if (!pRuntime->IsBlocking())
677	{
678		IFXJS_Context* pContext = pRuntime->NewContext();
679		ASSERT(pContext != NULL);
680		pContext->OnExternal_Exec();
681		CFX_WideString wtInfo;
682		pContext->RunScript(wsScript,wtInfo);
683		pRuntime->ReleaseContext(pContext);
684	}
685}
686
687FX_BOOL app::goBack(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
688{
689  // Not supported.
690  return TRUE;
691}
692
693FX_BOOL app::goForward(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
694{
695  // Not supported.
696  return TRUE;
697}
698
699FX_BOOL app::mailMsg(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
700{
701	CJS_Context* pContext = (CJS_Context*)cc;
702	v8::Isolate* isolate = GetIsolate(cc);
703
704	FX_BOOL bUI = TRUE;
705	CFX_WideString cTo = L"";
706	CFX_WideString cCc = L"";
707	CFX_WideString cBcc = L"";
708	CFX_WideString cSubject = L"";
709	CFX_WideString cMsg = L"";
710
711	if (params.size() < 1)
712		return FALSE;
713
714	if (params[0].GetType() == VT_object)
715	{
716		JSObject pObj = params[0].ToV8Object();
717
718		v8::Local<v8::Value> pValue = JS_GetObjectElement(isolate, pObj, L"bUI");
719		bUI = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToBool();
720
721		pValue = JS_GetObjectElement(isolate, pObj, L"cTo");
722		cTo = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
723
724		pValue = JS_GetObjectElement(isolate, pObj, L"cCc");
725		cCc = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
726
727		pValue = JS_GetObjectElement(isolate, pObj, L"cBcc");
728		cBcc = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
729
730		pValue = JS_GetObjectElement(isolate, pObj, L"cSubject");
731		cSubject = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
732
733		pValue = JS_GetObjectElement(isolate, pObj, L"cMsg");
734		cMsg = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
735	} else {
736		if (params.size() < 2)
737			return FALSE;
738
739		bUI = params[0].ToBool();
740		cTo = params[1].ToCFXWideString();
741
742		if (params.size() >= 3)
743			cCc = params[2].ToCFXWideString();
744		if (params.size() >= 4)
745			cBcc = params[3].ToCFXWideString();
746		if (params.size() >= 5)
747			cSubject = params[4].ToCFXWideString();
748		if (params.size() >= 6)
749			cMsg = params[5].ToCFXWideString();
750	}
751
752	CJS_Runtime* pRuntime = pContext->GetJSRuntime();
753	ASSERT(pRuntime != NULL);
754
755	CPDFDoc_Environment* pApp = pContext->GetReaderApp();
756	ASSERT(pApp != NULL);
757
758	pRuntime->BeginBlock();
759	pApp->JS_docmailForm(NULL, 0, bUI, cTo.c_str(), cSubject.c_str(), cCc.c_str(), cBcc.c_str(), cMsg.c_str());
760	pRuntime->EndBlock();
761
762	return FALSE;
763}
764
765FX_BOOL app::launchURL(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
766{
767  // Unsafe, not supported.
768  return TRUE;
769}
770
771FX_BOOL app::runtimeHighlight(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
772{
773	if (vp.IsSetting())
774	{
775		vp>>m_bRuntimeHighLight;
776	}
777	else
778	{
779		vp<<m_bRuntimeHighLight;
780	}
781
782	return TRUE;
783}
784
785FX_BOOL app::fullscreen(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
786{
787	return FALSE;
788}
789
790FX_BOOL app::popUpMenu(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
791{
792	return FALSE;
793}
794
795
796FX_BOOL app::browseForDoc(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
797{
798  // Unsafe, not supported.
799  return TRUE;
800}
801
802CFX_WideString app::SysPathToPDFPath(const CFX_WideString& sOldPath)
803{
804	CFX_WideString sRet = L"/";
805
806	for (int i=0,sz=sOldPath.GetLength(); i<sz; i++)
807	{
808		wchar_t c = sOldPath.GetAt(i);
809		if (c == L':')
810		{
811		}
812		else
813		{
814			if (c == L'\\')
815			{
816				sRet += L"/";
817			}
818			else
819			{
820				sRet += c;
821			}
822		}
823	}
824
825	return sRet;
826}
827
828FX_BOOL app::newDoc(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
829{
830	return FALSE;
831}
832
833FX_BOOL app::openDoc(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
834{
835	return FALSE;
836}
837
838FX_BOOL app::response(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
839{
840	CFX_WideString swQuestion = L"";
841	CFX_WideString swLabel = L"";
842	CFX_WideString swTitle = L"PDF";
843	CFX_WideString swDefault = L"";
844	bool bPassWord = false;
845
846	v8::Isolate* isolate = GetIsolate(cc);
847
848	int iLength = params.size();
849	if (iLength > 0 && params[0].GetType() == VT_object)
850	{
851		JSObject pObj = params[0].ToV8Object();
852		v8::Local<v8::Value> pValue = JS_GetObjectElement(isolate,pObj,L"cQuestion");
853		swQuestion = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).ToCFXWideString();
854
855		pValue = JS_GetObjectElement(isolate,pObj,L"cTitle");
856		swTitle = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).ToCFXWideString();
857
858		pValue = JS_GetObjectElement(isolate,pObj,L"cDefault");
859		swDefault = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).ToCFXWideString();
860
861		pValue = JS_GetObjectElement(isolate,pObj,L"cLabel");
862		swLabel = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).ToCFXWideString();
863
864		pValue = JS_GetObjectElement(isolate,pObj,L"bPassword");
865		bPassWord = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).ToBool();
866	}
867	else
868	{
869		switch(iLength)
870		{
871		case 5:
872			swLabel = params[4].ToCFXWideString();
873			// FALLTHROUGH
874		case 4:
875			bPassWord = params[3].ToBool();
876			// FALLTHROUGH
877		case 3:
878			swDefault = params[2].ToCFXWideString();
879			// FALLTHROUGH
880		case 2:
881			swTitle = params[1].ToCFXWideString();
882			// FALLTHROUGH
883		case 1:
884			swQuestion = params[0].ToCFXWideString();
885			// FALLTHROUGH
886		default:
887			break;
888		}
889	}
890
891	CJS_Context* pContext = (CJS_Context *)cc;
892	ASSERT(pContext != NULL);
893
894	CPDFDoc_Environment* pApp = pContext->GetReaderApp();
895	ASSERT(pApp != NULL);
896
897	const int MAX_INPUT_BYTES = 2048;
898	char* pBuff = new char[MAX_INPUT_BYTES + 2];
899	if (!pBuff)
900		return FALSE;
901
902	memset(pBuff, 0, MAX_INPUT_BYTES + 2);
903	int nLengthBytes = pApp->JS_appResponse(swQuestion.c_str(), swTitle.c_str(), swDefault.c_str(),
904                                            swLabel.c_str(), bPassWord, pBuff, MAX_INPUT_BYTES);
905	if (nLengthBytes <= 0)
906	{
907		vRet.SetNull();
908		delete[] pBuff;
909		return FALSE;
910	}
911	if (nLengthBytes > MAX_INPUT_BYTES)
912		nLengthBytes = MAX_INPUT_BYTES;
913
914	vRet = CFX_WideString::FromUTF16LE((unsigned short*)pBuff, nLengthBytes / sizeof(unsigned short)).c_str();
915	delete[] pBuff;
916	return TRUE;
917}
918
919FX_BOOL app::media(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
920{
921	return FALSE;
922}
923
924FX_BOOL app::execDialog(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
925{
926	return TRUE;
927}
928