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