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