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