• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_EventHandler.h"
10 #include "../../include/javascript/JS_Runtime.h"
11 #include "../../include/javascript/JS_Context.h"
12 #include "../../include/javascript/JS_Define.h"
13 #include "../../include/javascript/JS_Object.h"
14 #include "../../include/javascript/JS_Value.h"
15 #include "../../include/javascript/Document.h"
16 #include "../../include/javascript/app.h"
17 #include "../../include/javascript/color.h"
18 #include "../../include/javascript/Consts.h"
19 #include "../../include/javascript/Document.h"
20 #include "../../include/javascript/event.h"
21 #include "../../include/javascript/Field.h"
22 #include "../../include/javascript/Icon.h"
23 #include "../../include/javascript/PublicMethods.h"
24 #include "../../include/javascript/report.h"
25 #include "../../include/javascript/util.h"
26 #include "../../include/javascript/JS_GlobalData.h"
27 #include "../../include/javascript/global.h"
28 #include "../../include/javascript/console.h"
29 
~CJS_RuntimeFactory()30 CJS_RuntimeFactory::~CJS_RuntimeFactory()
31 {
32 }
33 
NewJSRuntime(CPDFDoc_Environment * pApp)34 IFXJS_Runtime*					CJS_RuntimeFactory::NewJSRuntime(CPDFDoc_Environment* pApp)
35 {
36 	if (!m_bInit)
37 	{
38 		JS_Initial();
39 
40 		m_bInit = TRUE;
41 	}
42 	return new CJS_Runtime(pApp);
43 }
AddRef()44 void							CJS_RuntimeFactory::AddRef()
45 {
46 	//to do.Should be implemented as atom manipulation.
47 	m_nRef++;
48 }
Release()49 void							CJS_RuntimeFactory::Release()
50 {
51 	if(m_bInit)
52 	{
53 		//to do.Should be implemented as atom manipulation.
54 		if (--m_nRef == 0)
55 		{
56 			JS_Release();
57 			ReleaseGlobalData();
58 			m_bInit = FALSE;
59 		}
60 	}
61 }
62 
DeleteJSRuntime(IFXJS_Runtime * pRuntime)63 void							CJS_RuntimeFactory::DeleteJSRuntime(IFXJS_Runtime* pRuntime)
64 {
65 	if(pRuntime)
66 		delete (CJS_Runtime*)pRuntime;
67 }
68 
NewGlobalData(CPDFDoc_Environment * pApp)69 CJS_GlobalData*	CJS_RuntimeFactory::NewGlobalData(CPDFDoc_Environment* pApp)
70 {
71 	if (m_pGlobalData)
72 	{
73 		m_nGlobalDataCount++;
74 		return m_pGlobalData;
75 	}
76 	else
77 	{
78 		m_nGlobalDataCount = 1;
79 		m_pGlobalData = new CJS_GlobalData(pApp);
80 		return m_pGlobalData;
81 	}
82 }
83 
ReleaseGlobalData()84 void CJS_RuntimeFactory::ReleaseGlobalData()
85 {
86 	m_nGlobalDataCount--;
87 
88 	if (m_nGlobalDataCount <= 0)
89 	{
90  		delete m_pGlobalData;
91  		m_pGlobalData = NULL;
92 	}
93 }
94 
95 /* ------------------------------ CJS_Runtime ------------------------------ */
96 
CJS_Runtime(CPDFDoc_Environment * pApp)97 CJS_Runtime::CJS_Runtime(CPDFDoc_Environment * pApp) :
98 	m_pApp(pApp),
99 	m_pDocument(NULL),
100 	m_pFieldEventPath(NULL),
101 	m_bBlocking(FALSE),
102 	m_bRegistered(FALSE)
103 {
104 	m_isolate = v8::Isolate::New();
105 	//m_isolate->Enter();
106 
107 	InitJSObjects();
108 
109 	CJS_Context * pContext = (CJS_Context*)NewContext();
110 	JS_InitialRuntime(*this, this, pContext, m_context);
111 	ReleaseContext(pContext);
112 }
113 
~CJS_Runtime()114 CJS_Runtime::~CJS_Runtime()
115 {
116 	for (int i=0, sz=m_ContextArray.GetSize(); i<sz; i++)
117 		delete m_ContextArray.GetAt(i);
118 
119 	m_ContextArray.RemoveAll();
120 
121 	JS_ReleaseRuntime(*this, m_context);
122 
123 	RemoveEventsInLoop(m_pFieldEventPath);
124 
125 	m_pApp = NULL;
126 	m_pDocument = NULL;
127 	m_pFieldEventPath = NULL;
128 	m_context.Reset();
129 
130 	//m_isolate->Exit();
131 	m_isolate->Dispose();
132 }
133 
InitJSObjects()134 FX_BOOL CJS_Runtime::InitJSObjects()
135 {
136 	v8::Isolate::Scope isolate_scope(GetIsolate());
137 	v8::HandleScope handle_scope(GetIsolate());
138 	v8::Handle<v8::Context> context = v8::Context::New(GetIsolate());
139 	v8::Context::Scope context_scope(context);
140 	//0 - 8
141 	if (CJS_Border::Init(*this, JS_STATIC) < 0) return FALSE;
142 	if (CJS_Display::Init(*this, JS_STATIC) < 0) return FALSE;
143 	if (CJS_Font::Init(*this, JS_STATIC) < 0) return FALSE;
144 	if (CJS_Highlight::Init(*this, JS_STATIC) < 0) return FALSE;
145 	if (CJS_Position::Init(*this, JS_STATIC) < 0) return FALSE;
146 	if (CJS_ScaleHow::Init(*this, JS_STATIC) < 0) return FALSE;
147 	if (CJS_ScaleWhen::Init(*this, JS_STATIC) < 0) return FALSE;
148 	if (CJS_Style::Init(*this, JS_STATIC) < 0) return FALSE;
149 	if (CJS_Zoomtype::Init(*this, JS_STATIC) < 0) return FALSE;
150 
151 	//9 - 11
152 	if (CJS_App::Init(*this, JS_STATIC) < 0) return FALSE;
153 	if (CJS_Color::Init(*this, JS_STATIC) < 0) return FALSE;
154 	if (CJS_Console::Init(*this, JS_STATIC) < 0) return FALSE;
155 
156 	//12 - 14
157 	if (CJS_Document::Init(*this, JS_DYNAMIC) < 0) return FALSE;
158 	if (CJS_Event::Init(*this, JS_STATIC) < 0) return FALSE;
159 	if (CJS_Field::Init(*this, JS_DYNAMIC) < 0) return FALSE;
160 
161 	//15 - 17
162 	if (CJS_Global::Init(*this, JS_STATIC) < 0) return FALSE;
163 	if (CJS_Icon::Init(*this, JS_DYNAMIC) < 0) return FALSE;
164 	if (CJS_Util::Init(*this, JS_STATIC) < 0) return FALSE;
165 
166 	if (CJS_PublicMethods::Init(*this) < 0) return FALSE;
167 	if (CJS_GlobalConsts::Init(*this) < 0) return FALSE;
168 	if (CJS_GlobalArrays::Init(*this) < 0) return FALSE;
169 
170 	if (CJS_TimerObj::Init(*this, JS_DYNAMIC) < 0) return FALSE;
171 	if (CJS_PrintParamsObj::Init(*this, JS_DYNAMIC) <0) return FALSE;
172 
173 	return TRUE;
174 }
175 
NewContext()176 IFXJS_Context* CJS_Runtime::NewContext()
177 {
178 	CJS_Context * p = new CJS_Context(this);
179 	m_ContextArray.Add(p);
180 	return p;
181 }
182 
ReleaseContext(IFXJS_Context * pContext)183 void CJS_Runtime::ReleaseContext(IFXJS_Context * pContext)
184 {
185 	CJS_Context* pJSContext = (CJS_Context*)pContext;
186 
187 	for (int i=0, sz=m_ContextArray.GetSize(); i<sz; i++)
188 	{
189 		if (pJSContext == m_ContextArray.GetAt(i))
190 		{
191 			delete pJSContext;
192 			m_ContextArray.RemoveAt(i);
193 			break;
194 		}
195 	}
196 }
197 
GetCurrentContext()198 IFXJS_Context*	CJS_Runtime::GetCurrentContext()
199 {
200 	if(!m_ContextArray.GetSize())
201 		return NULL;
202 	return m_ContextArray.GetAt(m_ContextArray.GetSize()-1);
203 }
204 
SetReaderDocument(CPDFSDK_Document * pReaderDoc)205 void CJS_Runtime::SetReaderDocument(CPDFSDK_Document* pReaderDoc)
206 {
207 	if (m_pDocument != pReaderDoc)
208 	{
209 		v8::Isolate::Scope isolate_scope(m_isolate);
210 		v8::HandleScope handle_scope(m_isolate);
211 		v8::Local<v8::Context> context =v8::Local<v8::Context>::New(m_isolate, m_context);
212 		v8::Context::Scope context_scope(context);
213 
214 		m_pDocument = pReaderDoc;
215 
216 		if (pReaderDoc)
217 		{
218 			JSObject pThis = JS_GetThisObj(*this);
219 			if(!pThis.IsEmpty())
220 			{
221 				if (JS_GetObjDefnID(pThis) == JS_GetObjDefnID(*this, L"Document"))
222 				{
223 					if (CJS_Document* pJSDocument = (CJS_Document*)JS_GetPrivate(pThis))
224 					{
225 						if (Document * pDocument = (Document*)pJSDocument->GetEmbedObject())
226 							pDocument->AttachDoc(pReaderDoc);
227 					}
228 				}
229 			}
230 			JS_SetThisObj(*this, JS_GetObjDefnID(*this, L"Document"));
231 		}
232 		else
233 		{
234 			JS_SetThisObj(*this, JS_GetObjDefnID(*this, L"app"));
235 		}
236 	}
237 }
238 
AddEventToLoop(const CFX_WideString & sTargetName,JS_EVENT_T eEventType)239 FX_BOOL	CJS_Runtime::AddEventToLoop(const CFX_WideString& sTargetName, JS_EVENT_T eEventType)
240 {
241 	if (m_pFieldEventPath == NULL)
242 	{
243 		m_pFieldEventPath = new CJS_FieldEvent;
244 		m_pFieldEventPath->sTargetName = sTargetName;
245 		m_pFieldEventPath->eEventType = eEventType;
246 		m_pFieldEventPath->pNext = NULL;
247 
248 		return TRUE;
249 	}
250 
251 	//to search
252 	CJS_FieldEvent* p = m_pFieldEventPath;
253 	CJS_FieldEvent* pLast = m_pFieldEventPath;
254 	while (p)
255 	{
256 		if (p->eEventType == eEventType && p->sTargetName == sTargetName)
257 			return FALSE;
258 
259 		pLast = p;
260 		p = p->pNext;
261 	}
262 
263 	//to add
264 	CJS_FieldEvent* pNew = new CJS_FieldEvent;
265 	pNew->sTargetName = sTargetName;
266 	pNew->eEventType = eEventType;
267 	pNew->pNext = NULL;
268 
269 	pLast->pNext = pNew;
270 
271 	return TRUE;
272 }
273 
RemoveEventInLoop(const CFX_WideString & sTargetName,JS_EVENT_T eEventType)274 void CJS_Runtime::RemoveEventInLoop(const CFX_WideString& sTargetName, JS_EVENT_T eEventType)
275 {
276 	FX_BOOL bFind = FALSE;
277 
278 	CJS_FieldEvent* p = m_pFieldEventPath;
279 	CJS_FieldEvent* pLast = NULL;
280 	while (p)
281 	{
282 		if (p->eEventType == eEventType && p->sTargetName == sTargetName)
283 		{
284 			bFind = TRUE;
285 			break;
286 		}
287 
288 		pLast = p;
289 		p = p->pNext;
290 	}
291 
292 	if (bFind)
293 	{
294 		RemoveEventsInLoop(p);
295 
296 		if (p == m_pFieldEventPath)
297 			m_pFieldEventPath = NULL;
298 
299 		if (pLast)
300 			pLast->pNext = NULL;
301 	}
302 }
303 
RemoveEventsInLoop(CJS_FieldEvent * pStart)304 void CJS_Runtime::RemoveEventsInLoop(CJS_FieldEvent* pStart)
305 {
306 	CJS_FieldEvent* p = pStart;
307 
308 	while (p)
309 	{
310 		CJS_FieldEvent* pOld = p;
311 		p = pOld->pNext;
312 
313 		delete pOld;
314 	}
315 }
316 
NewJSContext()317 v8::Handle<v8::Context>	CJS_Runtime::NewJSContext()
318 {
319 	return v8::Local<v8::Context>::New(m_isolate, m_context);
320 }
321 
ChangeObjName(const CFX_WideString & str)322 CFX_WideString ChangeObjName(const CFX_WideString& str)
323 {
324 	CFX_WideString sRet = str;
325 	sRet.Replace((FX_LPCWSTR)L"_", (FX_LPCWSTR)L".");
326 	return sRet;
327 }
328 
GetObjectNames(CFX_WideStringArray & array)329 void CJS_Runtime::GetObjectNames(CFX_WideStringArray& array)
330 {
331 	array.RemoveAll();
332 
333 	array.Add(CJS_Border::m_pClassName);
334 	array.Add(CJS_Display::m_pClassName);
335 	array.Add(CJS_Font::m_pClassName);
336 	array.Add(CJS_Highlight::m_pClassName);
337 	array.Add(CJS_Position::m_pClassName);
338 	array.Add(CJS_ScaleHow::m_pClassName);
339 	array.Add(CJS_ScaleWhen::m_pClassName);
340 	array.Add(CJS_Style::m_pClassName);
341 	array.Add(CJS_Zoomtype::m_pClassName);
342 
343 	array.Add(CJS_App::m_pClassName);
344 	array.Add((FX_LPCWSTR)"this");
345 	array.Add(CJS_Event::m_pClassName);
346 
347 	array.Add(CJS_Global::m_pClassName);
348 	array.Add(CJS_Util::m_pClassName);
349 }
350 
GetObjectConsts(const CFX_WideString & sObjName,CFX_WideStringArray & array)351 void CJS_Runtime::GetObjectConsts(const CFX_WideString& sObjName, CFX_WideStringArray& array)
352 {
353 	JSConstSpec* pConsts = NULL;
354 	int nSize = 0;
355 
356 	if (sObjName == CJS_Border::m_pClassName)
357 		CJS_Border::GetConsts(pConsts, nSize);
358 	else if (sObjName == CJS_Display::m_pClassName)
359 		CJS_Display::GetConsts(pConsts, nSize);
360 	else if (sObjName == CJS_Font::m_pClassName)
361 		CJS_Font::GetConsts(pConsts, nSize);
362 	else if (sObjName == CJS_Highlight::m_pClassName)
363 		CJS_Highlight::GetConsts(pConsts, nSize);
364 	else if (sObjName == CJS_Position::m_pClassName)
365 		CJS_Position::GetConsts(pConsts, nSize);
366 	else if (sObjName == CJS_ScaleHow::m_pClassName)
367 		CJS_ScaleHow::GetConsts(pConsts, nSize);
368 	else if (sObjName == CJS_ScaleWhen::m_pClassName)
369 		CJS_ScaleWhen::GetConsts(pConsts, nSize);
370 	else if (sObjName == CJS_Style::m_pClassName)
371 		CJS_Style::GetConsts(pConsts, nSize);
372 	else if (sObjName == CJS_Zoomtype::m_pClassName)
373 		CJS_Zoomtype::GetConsts(pConsts, nSize);
374 
375 	else if (sObjName == CJS_App::m_pClassName)
376 		CJS_App::GetConsts(pConsts, nSize);
377 	else if (sObjName == CJS_Color::m_pClassName)
378 		CJS_Color::GetConsts(pConsts, nSize);
379 
380 	else if (sObjName == L"this")
381 	{
382 		if (GetReaderDocument())
383 			CJS_Document::GetConsts(pConsts, nSize);
384 		else
385 			CJS_App::GetConsts(pConsts, nSize);
386 	}
387 
388 	if (sObjName == CJS_Event::m_pClassName)
389 		CJS_Event::GetConsts(pConsts, nSize);
390 	else if (sObjName == CJS_Field::m_pClassName)
391 		CJS_Field::GetConsts(pConsts, nSize);
392 	else if (sObjName == CJS_Global::m_pClassName)
393 		CJS_Global::GetConsts(pConsts, nSize);
394 	else if (sObjName == CJS_Util::m_pClassName)
395 		CJS_Util::GetConsts(pConsts, nSize);
396 
397 	for (int i=0; i<nSize; i++)
398 		array.Add(pConsts[i].pName);
399 }
400 
GetObjectProps(const CFX_WideString & sObjName,CFX_WideStringArray & array)401 void CJS_Runtime::GetObjectProps(const CFX_WideString& sObjName, CFX_WideStringArray& array)
402 {
403 	JSPropertySpec* pProperties = NULL;
404 	int nSize = 0;
405 
406  	if (sObjName == CJS_App::m_pClassName)
407 		CJS_App::GetProperties(pProperties, nSize);
408 	else if (sObjName == CJS_Color::m_pClassName)
409 		CJS_Color::GetProperties(pProperties, nSize);
410 	else if (sObjName == L"this")
411 	{
412 		if (GetReaderDocument())
413 			CJS_Document::GetProperties(pProperties, nSize);
414 		else
415 			CJS_App::GetProperties(pProperties, nSize);
416 	}
417 	else if (sObjName == CJS_Event::m_pClassName)
418 		CJS_Event::GetProperties(pProperties, nSize);
419 	else if (sObjName == CJS_Field::m_pClassName)
420 		CJS_Field::GetProperties(pProperties, nSize);
421 	else if (sObjName == CJS_Global::m_pClassName)
422 		CJS_Global::GetProperties(pProperties, nSize);
423 	else if (sObjName == CJS_Util::m_pClassName)
424 		CJS_Util::GetProperties(pProperties, nSize);
425 
426 	for (int i=0; i<nSize; i++)
427 		array.Add(pProperties[i].pName);
428 }
429 
GetObjectMethods(const CFX_WideString & sObjName,CFX_WideStringArray & array)430 void CJS_Runtime::GetObjectMethods(const CFX_WideString& sObjName, CFX_WideStringArray& array)
431 {
432 	JSMethodSpec* pMethods = NULL;
433 	int nSize = 0;
434 
435  	 if (sObjName == CJS_App::m_pClassName)
436 		CJS_App::GetMethods(pMethods, nSize);
437 	else if (sObjName == CJS_Color::m_pClassName)
438 		CJS_Color::GetMethods(pMethods, nSize);
439 	else if (sObjName == L"this")
440 	{
441 		if (GetReaderDocument())
442 			CJS_Document::GetMethods(pMethods, nSize);
443 		else
444 			CJS_App::GetMethods(pMethods, nSize);
445 	}
446 	else if (sObjName == CJS_Event::m_pClassName)
447 		CJS_Event::GetMethods(pMethods, nSize);
448 	else if (sObjName == CJS_Field::m_pClassName)
449 		CJS_Field::GetMethods(pMethods, nSize);
450 	else if (sObjName == CJS_Global::m_pClassName)
451 		CJS_Global::GetMethods(pMethods, nSize);
452 	else if (sObjName == CJS_Util::m_pClassName)
453 		CJS_Util::GetMethods(pMethods, nSize);
454 
455 	for (int i=0; i<nSize; i++)
456 		array.Add(pMethods[i].pName);
457 }
458 
IsEntered()459 FX_BOOL  CJS_Runtime::IsEntered()
460 {
461 	return v8::Isolate::GetCurrent() == m_isolate;
462 }
Exit()463 void	CJS_Runtime::Exit()
464 {
465 	if(m_isolate) m_isolate->Exit();
466 }
Enter()467 void	CJS_Runtime::Enter()
468 {
469 	if(m_isolate) m_isolate->Enter();
470 }
471