blob: 197d7b4e6f3f8873ee0c1566be9b5c6876e559cc [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"
Bo Xufdc00a72014-10-28 23:03:33 -070029#include "../../include/fpdfxfa/fpdfxfa_app.h"
30#ifndef FOXIT_CHROME_BUILD
31#include "../../../fxjse/value.h"
32#else
33#include "../../../xfa/src/fxjse/src/value.h"
34#endif
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070035
Jochen Eisinger3fb18f42014-07-17 08:46:45 +020036#include <libplatform/libplatform.h>
37
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070038CJS_RuntimeFactory::~CJS_RuntimeFactory()
39{
40}
41
42IFXJS_Runtime* CJS_RuntimeFactory::NewJSRuntime(CPDFDoc_Environment* pApp)
43{
44 if (!m_bInit)
45 {
46 JS_Initial();
Bo Xuca979402014-10-29 16:12:02 -070047/*
Jochen Eisinger3fb18f42014-07-17 08:46:45 +020048 m_platform = v8::platform::CreateDefaultPlatform();
49 v8::V8::InitializePlatform(m_platform);
Jochen Eisinger0c533242014-09-22 08:46:17 +020050 v8::V8::Initialize();
Bo Xuca979402014-10-29 16:12:02 -070051*/
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070052 m_bInit = TRUE;
53 }
54 return new CJS_Runtime(pApp);
55}
56void CJS_RuntimeFactory::AddRef()
57{
58 //to do.Should be implemented as atom manipulation.
59 m_nRef++;
60}
61void CJS_RuntimeFactory::Release()
62{
63 if(m_bInit)
64 {
65 //to do.Should be implemented as atom manipulation.
66 if (--m_nRef == 0)
67 {
68 JS_Release();
69 ReleaseGlobalData();
Jochen Eisinger3fb18f42014-07-17 08:46:45 +020070 v8::V8::ShutdownPlatform();
71 delete m_platform;
72 m_platform = NULL;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070073 m_bInit = FALSE;
74 }
75 }
76}
77
78void CJS_RuntimeFactory::DeleteJSRuntime(IFXJS_Runtime* pRuntime)
79{
80 if(pRuntime)
81 delete (CJS_Runtime*)pRuntime;
82}
83
84CJS_GlobalData* CJS_RuntimeFactory::NewGlobalData(CPDFDoc_Environment* pApp)
85{
86 if (m_pGlobalData)
87 {
88 m_nGlobalDataCount++;
89 return m_pGlobalData;
90 }
91 else
92 {
93 m_nGlobalDataCount = 1;
94 m_pGlobalData = new CJS_GlobalData(pApp);
95 return m_pGlobalData;
96 }
97}
98
99void CJS_RuntimeFactory::ReleaseGlobalData()
100{
101 m_nGlobalDataCount--;
102
103 if (m_nGlobalDataCount <= 0)
104 {
105 delete m_pGlobalData;
106 m_pGlobalData = NULL;
107 }
108}
109
110/* ------------------------------ CJS_Runtime ------------------------------ */
Bo Xufdc00a72014-10-28 23:03:33 -0700111extern v8::Persistent<v8::ObjectTemplate>& _getGlobalObjectTemplate(IJS_Runtime* pJSRuntime);
112CJS_Runtime::CJS_Runtime(CPDFDoc_Environment* pApp) :
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700113 m_pApp(pApp),
114 m_pDocument(NULL),
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700115 m_bBlocking(FALSE),
Nico Weber09363c82014-07-31 10:07:04 -0700116 m_pFieldEventPath(NULL),
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700117 m_bRegistered(FALSE)
118{
Bo Xufdc00a72014-10-28 23:03:33 -0700119 m_isolate = FPDFXFA_GetApp()->GetJSERuntime()?(v8::Isolate*)FPDFXFA_GetApp()->GetJSERuntime():v8::Isolate::New();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700120 //m_isolate->Enter();
Bo Xufdc00a72014-10-28 23:03:33 -0700121 v8::Isolate* isolate = m_isolate;
122 v8::Isolate::Scope isolate_scope(isolate);
123 v8::Locker locker(isolate);
124 v8::HandleScope handle_scope(isolate);
125 if (FPDFXFA_GetApp()->InitRuntime(FALSE)) {
126 CJS_Context * pContext = (CJS_Context*)NewContext();
127 JS_InitialRuntime(*this, this, pContext, m_context);
128 ReleaseContext(pContext);
129 return;
130 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700131
132 InitJSObjects();
133
134 CJS_Context * pContext = (CJS_Context*)NewContext();
135 JS_InitialRuntime(*this, this, pContext, m_context);
136 ReleaseContext(pContext);
137}
138
139CJS_Runtime::~CJS_Runtime()
140{
Bo Xufdc00a72014-10-28 23:03:33 -0700141 int size = m_ContextArray.GetSize();
142 for (int i=0;i < size; i++)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700143 delete m_ContextArray.GetAt(i);
144
145 m_ContextArray.RemoveAll();
146
Bo Xufdc00a72014-10-28 23:03:33 -0700147 //JS_ReleaseRuntime(*this, m_context);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700148
149 RemoveEventsInLoop(m_pFieldEventPath);
150
151 m_pApp = NULL;
152 m_pDocument = NULL;
153 m_pFieldEventPath = NULL;
154 m_context.Reset();
155
156 //m_isolate->Exit();
Bo Xufdc00a72014-10-28 23:03:33 -0700157 //m_isolate->Dispose();
158 m_isolate = NULL;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700159}
160
161FX_BOOL CJS_Runtime::InitJSObjects()
162{
163 v8::Isolate::Scope isolate_scope(GetIsolate());
Bo Xufdc00a72014-10-28 23:03:33 -0700164 v8::Locker locker(GetIsolate());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700165 v8::HandleScope handle_scope(GetIsolate());
166 v8::Handle<v8::Context> context = v8::Context::New(GetIsolate());
167 v8::Context::Scope context_scope(context);
168 //0 - 8
169 if (CJS_Border::Init(*this, JS_STATIC) < 0) return FALSE;
170 if (CJS_Display::Init(*this, JS_STATIC) < 0) return FALSE;
171 if (CJS_Font::Init(*this, JS_STATIC) < 0) return FALSE;
172 if (CJS_Highlight::Init(*this, JS_STATIC) < 0) return FALSE;
173 if (CJS_Position::Init(*this, JS_STATIC) < 0) return FALSE;
174 if (CJS_ScaleHow::Init(*this, JS_STATIC) < 0) return FALSE;
175 if (CJS_ScaleWhen::Init(*this, JS_STATIC) < 0) return FALSE;
176 if (CJS_Style::Init(*this, JS_STATIC) < 0) return FALSE;
177 if (CJS_Zoomtype::Init(*this, JS_STATIC) < 0) return FALSE;
178
179 //9 - 11
180 if (CJS_App::Init(*this, JS_STATIC) < 0) return FALSE;
181 if (CJS_Color::Init(*this, JS_STATIC) < 0) return FALSE;
182 if (CJS_Console::Init(*this, JS_STATIC) < 0) return FALSE;
183
184 //12 - 14
185 if (CJS_Document::Init(*this, JS_DYNAMIC) < 0) return FALSE;
186 if (CJS_Event::Init(*this, JS_STATIC) < 0) return FALSE;
187 if (CJS_Field::Init(*this, JS_DYNAMIC) < 0) return FALSE;
188
189 //15 - 17
190 if (CJS_Global::Init(*this, JS_STATIC) < 0) return FALSE;
191 if (CJS_Icon::Init(*this, JS_DYNAMIC) < 0) return FALSE;
192 if (CJS_Util::Init(*this, JS_STATIC) < 0) return FALSE;
193
194 if (CJS_PublicMethods::Init(*this) < 0) return FALSE;
195 if (CJS_GlobalConsts::Init(*this) < 0) return FALSE;
196 if (CJS_GlobalArrays::Init(*this) < 0) return FALSE;
197
198 if (CJS_TimerObj::Init(*this, JS_DYNAMIC) < 0) return FALSE;
199 if (CJS_PrintParamsObj::Init(*this, JS_DYNAMIC) <0) return FALSE;
200
201 return TRUE;
202}
203
204IFXJS_Context* CJS_Runtime::NewContext()
205{
206 CJS_Context * p = new CJS_Context(this);
207 m_ContextArray.Add(p);
208 return p;
209}
210
211void CJS_Runtime::ReleaseContext(IFXJS_Context * pContext)
212{
213 CJS_Context* pJSContext = (CJS_Context*)pContext;
214
215 for (int i=0, sz=m_ContextArray.GetSize(); i<sz; i++)
216 {
217 if (pJSContext == m_ContextArray.GetAt(i))
218 {
219 delete pJSContext;
220 m_ContextArray.RemoveAt(i);
221 break;
222 }
223 }
224}
225
226IFXJS_Context* CJS_Runtime::GetCurrentContext()
227{
228 if(!m_ContextArray.GetSize())
229 return NULL;
230 return m_ContextArray.GetAt(m_ContextArray.GetSize()-1);
231}
232
233void CJS_Runtime::SetReaderDocument(CPDFSDK_Document* pReaderDoc)
234{
235 if (m_pDocument != pReaderDoc)
236 {
237 v8::Isolate::Scope isolate_scope(m_isolate);
Bo Xufdc00a72014-10-28 23:03:33 -0700238 v8::Locker locker(m_isolate);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700239 v8::HandleScope handle_scope(m_isolate);
240 v8::Local<v8::Context> context =v8::Local<v8::Context>::New(m_isolate, m_context);
241 v8::Context::Scope context_scope(context);
242
243 m_pDocument = pReaderDoc;
244
245 if (pReaderDoc)
246 {
247 JSObject pThis = JS_GetThisObj(*this);
248 if(!pThis.IsEmpty())
249 {
250 if (JS_GetObjDefnID(pThis) == JS_GetObjDefnID(*this, L"Document"))
251 {
252 if (CJS_Document* pJSDocument = (CJS_Document*)JS_GetPrivate(pThis))
253 {
254 if (Document * pDocument = (Document*)pJSDocument->GetEmbedObject())
255 pDocument->AttachDoc(pReaderDoc);
256 }
257 }
258 }
259 JS_SetThisObj(*this, JS_GetObjDefnID(*this, L"Document"));
260 }
261 else
262 {
263 JS_SetThisObj(*this, JS_GetObjDefnID(*this, L"app"));
264 }
265 }
266}
267
268FX_BOOL CJS_Runtime::AddEventToLoop(const CFX_WideString& sTargetName, JS_EVENT_T eEventType)
269{
270 if (m_pFieldEventPath == NULL)
271 {
272 m_pFieldEventPath = new CJS_FieldEvent;
273 m_pFieldEventPath->sTargetName = sTargetName;
274 m_pFieldEventPath->eEventType = eEventType;
275 m_pFieldEventPath->pNext = NULL;
276
277 return TRUE;
278 }
279
280 //to search
281 CJS_FieldEvent* p = m_pFieldEventPath;
282 CJS_FieldEvent* pLast = m_pFieldEventPath;
283 while (p)
284 {
285 if (p->eEventType == eEventType && p->sTargetName == sTargetName)
286 return FALSE;
287
288 pLast = p;
289 p = p->pNext;
290 }
291
292 //to add
293 CJS_FieldEvent* pNew = new CJS_FieldEvent;
294 pNew->sTargetName = sTargetName;
295 pNew->eEventType = eEventType;
296 pNew->pNext = NULL;
297
298 pLast->pNext = pNew;
299
300 return TRUE;
301}
302
303void CJS_Runtime::RemoveEventInLoop(const CFX_WideString& sTargetName, JS_EVENT_T eEventType)
304{
305 FX_BOOL bFind = FALSE;
306
307 CJS_FieldEvent* p = m_pFieldEventPath;
308 CJS_FieldEvent* pLast = NULL;
309 while (p)
310 {
311 if (p->eEventType == eEventType && p->sTargetName == sTargetName)
312 {
313 bFind = TRUE;
314 break;
315 }
316
317 pLast = p;
318 p = p->pNext;
319 }
320
321 if (bFind)
322 {
323 RemoveEventsInLoop(p);
324
325 if (p == m_pFieldEventPath)
326 m_pFieldEventPath = NULL;
327
328 if (pLast)
329 pLast->pNext = NULL;
330 }
331}
332
333void CJS_Runtime::RemoveEventsInLoop(CJS_FieldEvent* pStart)
334{
335 CJS_FieldEvent* p = pStart;
336
337 while (p)
338 {
339 CJS_FieldEvent* pOld = p;
340 p = pOld->pNext;
341
342 delete pOld;
343 }
344}
345
346v8::Handle<v8::Context> CJS_Runtime::NewJSContext()
347{
348 return v8::Local<v8::Context>::New(m_isolate, m_context);
349}
350
351CFX_WideString ChangeObjName(const CFX_WideString& str)
352{
353 CFX_WideString sRet = str;
Bo Xuf13c1f32014-11-14 17:03:50 -0800354 sRet.Replace(L"_", L".");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700355 return sRet;
356}
357
358void CJS_Runtime::GetObjectNames(CFX_WideStringArray& array)
359{
360 array.RemoveAll();
361
362 array.Add(CJS_Border::m_pClassName);
363 array.Add(CJS_Display::m_pClassName);
364 array.Add(CJS_Font::m_pClassName);
365 array.Add(CJS_Highlight::m_pClassName);
366 array.Add(CJS_Position::m_pClassName);
367 array.Add(CJS_ScaleHow::m_pClassName);
368 array.Add(CJS_ScaleWhen::m_pClassName);
369 array.Add(CJS_Style::m_pClassName);
370 array.Add(CJS_Zoomtype::m_pClassName);
371
372 array.Add(CJS_App::m_pClassName);
Bo Xua197ba42014-11-14 14:18:05 -0800373 array.Add(L"this");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700374 array.Add(CJS_Event::m_pClassName);
375
376 array.Add(CJS_Global::m_pClassName);
377 array.Add(CJS_Util::m_pClassName);
378}
379
380void CJS_Runtime::GetObjectConsts(const CFX_WideString& sObjName, CFX_WideStringArray& array)
381{
382 JSConstSpec* pConsts = NULL;
383 int nSize = 0;
384
385 if (sObjName == CJS_Border::m_pClassName)
386 CJS_Border::GetConsts(pConsts, nSize);
387 else if (sObjName == CJS_Display::m_pClassName)
388 CJS_Display::GetConsts(pConsts, nSize);
389 else if (sObjName == CJS_Font::m_pClassName)
390 CJS_Font::GetConsts(pConsts, nSize);
391 else if (sObjName == CJS_Highlight::m_pClassName)
392 CJS_Highlight::GetConsts(pConsts, nSize);
393 else if (sObjName == CJS_Position::m_pClassName)
394 CJS_Position::GetConsts(pConsts, nSize);
395 else if (sObjName == CJS_ScaleHow::m_pClassName)
396 CJS_ScaleHow::GetConsts(pConsts, nSize);
397 else if (sObjName == CJS_ScaleWhen::m_pClassName)
398 CJS_ScaleWhen::GetConsts(pConsts, nSize);
399 else if (sObjName == CJS_Style::m_pClassName)
400 CJS_Style::GetConsts(pConsts, nSize);
401 else if (sObjName == CJS_Zoomtype::m_pClassName)
402 CJS_Zoomtype::GetConsts(pConsts, nSize);
403
404 else if (sObjName == CJS_App::m_pClassName)
405 CJS_App::GetConsts(pConsts, nSize);
406 else if (sObjName == CJS_Color::m_pClassName)
407 CJS_Color::GetConsts(pConsts, nSize);
408
409 else if (sObjName == L"this")
410 {
411 if (GetReaderDocument())
412 CJS_Document::GetConsts(pConsts, nSize);
413 else
414 CJS_App::GetConsts(pConsts, nSize);
415 }
416
417 if (sObjName == CJS_Event::m_pClassName)
418 CJS_Event::GetConsts(pConsts, nSize);
419 else if (sObjName == CJS_Field::m_pClassName)
420 CJS_Field::GetConsts(pConsts, nSize);
421 else if (sObjName == CJS_Global::m_pClassName)
422 CJS_Global::GetConsts(pConsts, nSize);
423 else if (sObjName == CJS_Util::m_pClassName)
424 CJS_Util::GetConsts(pConsts, nSize);
425
426 for (int i=0; i<nSize; i++)
427 array.Add(pConsts[i].pName);
428}
429
430void CJS_Runtime::GetObjectProps(const CFX_WideString& sObjName, CFX_WideStringArray& array)
431{
432 JSPropertySpec* pProperties = NULL;
433 int nSize = 0;
434
435 if (sObjName == CJS_App::m_pClassName)
436 CJS_App::GetProperties(pProperties, nSize);
437 else if (sObjName == CJS_Color::m_pClassName)
438 CJS_Color::GetProperties(pProperties, nSize);
439 else if (sObjName == L"this")
440 {
441 if (GetReaderDocument())
442 CJS_Document::GetProperties(pProperties, nSize);
443 else
444 CJS_App::GetProperties(pProperties, nSize);
445 }
446 else if (sObjName == CJS_Event::m_pClassName)
447 CJS_Event::GetProperties(pProperties, nSize);
448 else if (sObjName == CJS_Field::m_pClassName)
449 CJS_Field::GetProperties(pProperties, nSize);
450 else if (sObjName == CJS_Global::m_pClassName)
451 CJS_Global::GetProperties(pProperties, nSize);
452 else if (sObjName == CJS_Util::m_pClassName)
453 CJS_Util::GetProperties(pProperties, nSize);
454
455 for (int i=0; i<nSize; i++)
456 array.Add(pProperties[i].pName);
457}
458
459void CJS_Runtime::GetObjectMethods(const CFX_WideString& sObjName, CFX_WideStringArray& array)
460{
461 JSMethodSpec* pMethods = NULL;
462 int nSize = 0;
463
464 if (sObjName == CJS_App::m_pClassName)
465 CJS_App::GetMethods(pMethods, nSize);
466 else if (sObjName == CJS_Color::m_pClassName)
467 CJS_Color::GetMethods(pMethods, nSize);
468 else if (sObjName == L"this")
469 {
470 if (GetReaderDocument())
471 CJS_Document::GetMethods(pMethods, nSize);
472 else
473 CJS_App::GetMethods(pMethods, nSize);
474 }
475 else if (sObjName == CJS_Event::m_pClassName)
476 CJS_Event::GetMethods(pMethods, nSize);
477 else if (sObjName == CJS_Field::m_pClassName)
478 CJS_Field::GetMethods(pMethods, nSize);
479 else if (sObjName == CJS_Global::m_pClassName)
480 CJS_Global::GetMethods(pMethods, nSize);
481 else if (sObjName == CJS_Util::m_pClassName)
482 CJS_Util::GetMethods(pMethods, nSize);
483
484 for (int i=0; i<nSize; i++)
485 array.Add(pMethods[i].pName);
486}
487
488FX_BOOL CJS_Runtime::IsEntered()
489{
490 return v8::Isolate::GetCurrent() == m_isolate;
491}
492void CJS_Runtime::Exit()
493{
494 if(m_isolate) m_isolate->Exit();
495}
496void CJS_Runtime::Enter()
497{
498 if(m_isolate) m_isolate->Enter();
499}
Bo Xufdc00a72014-10-28 23:03:33 -0700500FX_BOOL CJS_Runtime::GetHValueByName(FX_BSTR utf8Name, FXJSE_HVALUE hValue)
501{
502 FX_LPCSTR name = utf8Name.GetCStr();
503
504 v8::Locker lock(GetIsolate());
505 v8::Isolate::Scope isolate_scope(GetIsolate());
506 v8::HandleScope handle_scope(GetIsolate());
507 v8::Local<v8::Context> context =
508 v8::Local<v8::Context>::New(GetIsolate(), m_context);
509 v8::Context::Scope context_scope(context);
510
511
512 //v8::Local<v8::Context> tmpCotext = v8::Local<v8::Context>::New(GetIsolate(), m_context);
513 v8::Local<v8::Value> propvalue = context->Global()->Get(v8::String::NewFromUtf8(GetIsolate(), name, v8::String::kNormalString, utf8Name.GetLength()));
514
515 if (propvalue.IsEmpty()) {
516 FXJSE_Value_SetUndefined(hValue);
517 return FALSE;
518 }
519 ((CFXJSE_Value*)hValue)->ForceSetValue(propvalue);
520
521 return TRUE;
522}
523FX_BOOL CJS_Runtime::SetHValueByName(FX_BSTR utf8Name, FXJSE_HVALUE hValue)
524{
525 if (utf8Name.IsEmpty() || hValue == NULL)
526 return FALSE;
527 FX_LPCSTR name = utf8Name.GetCStr();
528 v8::Isolate* pIsolate = GetIsolate();
529 v8::Locker lock(pIsolate);
530 v8::Isolate::Scope isolate_scope(pIsolate);
531 v8::HandleScope handle_scope(pIsolate);
532 v8::Local<v8::Context> context =
533 v8::Local<v8::Context>::New(pIsolate, m_context);
534 v8::Context::Scope context_scope(context);
535
536 //v8::Local<v8::Context> tmpCotext = v8::Local<v8::Context>::New(GetIsolate(), m_context);
537 v8::Local<v8::Value> propvalue = v8::Local<v8::Value>::New(GetIsolate(),((CFXJSE_Value*)hValue)->DirectGetValue());
538 context->Global()->Set(v8::String::NewFromUtf8(pIsolate, name, v8::String::kNormalString, utf8Name.GetLength()), propvalue);
539
540 return TRUE;
541}