blob: bfea274eed43e81f4a3adaea0a14629e3fcac899 [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.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// 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"
Bo Xufdc00a72014-10-28 23:03:33 -070030#include "../../../xfa/src/fxjse/src/value.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070031
32CJS_RuntimeFactory::~CJS_RuntimeFactory()
33{
34}
35
36IFXJS_Runtime* CJS_RuntimeFactory::NewJSRuntime(CPDFDoc_Environment* pApp)
37{
38 if (!m_bInit)
39 {
40 JS_Initial();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070041 m_bInit = TRUE;
42 }
43 return new CJS_Runtime(pApp);
44}
45void CJS_RuntimeFactory::AddRef()
46{
47 //to do.Should be implemented as atom manipulation.
48 m_nRef++;
49}
50void CJS_RuntimeFactory::Release()
Lei Zhanga6d9f0e2015-06-13 00:48:38 -070051{
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070052 if(m_bInit)
53 {
54 //to do.Should be implemented as atom manipulation.
55 if (--m_nRef == 0)
56 {
57 JS_Release();
58 ReleaseGlobalData();
59 m_bInit = FALSE;
60 }
61 }
62}
63
64void CJS_RuntimeFactory::DeleteJSRuntime(IFXJS_Runtime* pRuntime)
65{
Lei Zhang796c9082015-07-16 18:45:22 -070066 delete (CJS_Runtime*)pRuntime;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070067}
68
69CJS_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
84void CJS_RuntimeFactory::ReleaseGlobalData()
85{
86 m_nGlobalDataCount--;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -070087
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070088 if (m_nGlobalDataCount <= 0)
89 {
90 delete m_pGlobalData;
91 m_pGlobalData = NULL;
92 }
93}
94
Tom Sepezd2cc1b92015-04-30 15:19:03 -070095void* CJS_ArrayBufferAllocator::Allocate(size_t length) {
96 return calloc(1, length);
97}
98
99void* CJS_ArrayBufferAllocator::AllocateUninitialized(size_t length) {
100 return malloc(length);
101}
102
103void CJS_ArrayBufferAllocator::Free(void* data, size_t length) {
104 free(data);
105}
106
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700107/* ------------------------------ CJS_Runtime ------------------------------ */
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200108extern v8::Global<v8::ObjectTemplate>& _getGlobalObjectTemplate(IJS_Runtime* pJSRuntime);
Bo Xufdc00a72014-10-28 23:03:33 -0700109CJS_Runtime::CJS_Runtime(CPDFDoc_Environment* pApp) :
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700110 m_pApp(pApp),
111 m_pDocument(NULL),
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700112 m_bBlocking(FALSE),
Tom Sepezd2cc1b92015-04-30 15:19:03 -0700113 m_bRegistered(FALSE),
114 m_pFieldEventPath(NULL)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700115{
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700116 if (CPDFXFA_App::GetInstance()->GetJSERuntime()) {
117 m_isolate = (v8::Isolate*)CPDFXFA_App::GetInstance()->GetJSERuntime();
Tom Sepezd2cc1b92015-04-30 15:19:03 -0700118 } else {
119 m_pArrayBufferAllocator.reset(new CJS_ArrayBufferAllocator());
120 v8::Isolate::CreateParams params;
121 params.array_buffer_allocator = m_pArrayBufferAllocator.get();
122 m_isolate = v8::Isolate::New(params);
123 }
124
Bo Xufdc00a72014-10-28 23:03:33 -0700125 v8::Isolate* isolate = m_isolate;
126 v8::Isolate::Scope isolate_scope(isolate);
127 v8::Locker locker(isolate);
128 v8::HandleScope handle_scope(isolate);
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700129 if (CPDFXFA_App::GetInstance()->InitRuntime(FALSE)) {
Bo Xufdc00a72014-10-28 23:03:33 -0700130 CJS_Context * pContext = (CJS_Context*)NewContext();
131 JS_InitialRuntime(*this, this, pContext, m_context);
132 ReleaseContext(pContext);
133 return;
134 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700135
136 InitJSObjects();
137
138 CJS_Context * pContext = (CJS_Context*)NewContext();
139 JS_InitialRuntime(*this, this, pContext, m_context);
140 ReleaseContext(pContext);
141}
142
143CJS_Runtime::~CJS_Runtime()
144{
Bo Xufdc00a72014-10-28 23:03:33 -0700145 int size = m_ContextArray.GetSize();
146 for (int i=0;i < size; i++)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700147 delete m_ContextArray.GetAt(i);
148
149 m_ContextArray.RemoveAll();
150
Bo Xufdc00a72014-10-28 23:03:33 -0700151 //JS_ReleaseRuntime(*this, m_context);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700152
153 RemoveEventsInLoop(m_pFieldEventPath);
154
155 m_pApp = NULL;
156 m_pDocument = NULL;
157 m_pFieldEventPath = NULL;
158 m_context.Reset();
159
160 //m_isolate->Exit();
Bo Xufdc00a72014-10-28 23:03:33 -0700161 //m_isolate->Dispose();
162 m_isolate = NULL;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700163}
164
165FX_BOOL CJS_Runtime::InitJSObjects()
166{
167 v8::Isolate::Scope isolate_scope(GetIsolate());
Bo Xufdc00a72014-10-28 23:03:33 -0700168 v8::Locker locker(GetIsolate());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700169 v8::HandleScope handle_scope(GetIsolate());
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200170 v8::Local<v8::Context> context = v8::Context::New(GetIsolate());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700171 v8::Context::Scope context_scope(context);
172 //0 - 8
173 if (CJS_Border::Init(*this, JS_STATIC) < 0) return FALSE;
174 if (CJS_Display::Init(*this, JS_STATIC) < 0) return FALSE;
175 if (CJS_Font::Init(*this, JS_STATIC) < 0) return FALSE;
176 if (CJS_Highlight::Init(*this, JS_STATIC) < 0) return FALSE;
177 if (CJS_Position::Init(*this, JS_STATIC) < 0) return FALSE;
178 if (CJS_ScaleHow::Init(*this, JS_STATIC) < 0) return FALSE;
179 if (CJS_ScaleWhen::Init(*this, JS_STATIC) < 0) return FALSE;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700180 if (CJS_Style::Init(*this, JS_STATIC) < 0) return FALSE;
181 if (CJS_Zoomtype::Init(*this, JS_STATIC) < 0) return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700182
183 //9 - 11
184 if (CJS_App::Init(*this, JS_STATIC) < 0) return FALSE;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700185 if (CJS_Color::Init(*this, JS_STATIC) < 0) return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700186 if (CJS_Console::Init(*this, JS_STATIC) < 0) return FALSE;
187
188 //12 - 14
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700189 if (CJS_Document::Init(*this, JS_DYNAMIC) < 0) return FALSE;
190 if (CJS_Event::Init(*this, JS_STATIC) < 0) return FALSE;
191 if (CJS_Field::Init(*this, JS_DYNAMIC) < 0) return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700192
193 //15 - 17
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700194 if (CJS_Global::Init(*this, JS_STATIC) < 0) return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700195 if (CJS_Icon::Init(*this, JS_DYNAMIC) < 0) return FALSE;
196 if (CJS_Util::Init(*this, JS_STATIC) < 0) return FALSE;
197
198 if (CJS_PublicMethods::Init(*this) < 0) return FALSE;
199 if (CJS_GlobalConsts::Init(*this) < 0) return FALSE;
200 if (CJS_GlobalArrays::Init(*this) < 0) return FALSE;
201
202 if (CJS_TimerObj::Init(*this, JS_DYNAMIC) < 0) return FALSE;
203 if (CJS_PrintParamsObj::Init(*this, JS_DYNAMIC) <0) return FALSE;
204
205 return TRUE;
206}
207
208IFXJS_Context* CJS_Runtime::NewContext()
209{
210 CJS_Context * p = new CJS_Context(this);
211 m_ContextArray.Add(p);
212 return p;
213}
214
215void CJS_Runtime::ReleaseContext(IFXJS_Context * pContext)
216{
217 CJS_Context* pJSContext = (CJS_Context*)pContext;
218
219 for (int i=0, sz=m_ContextArray.GetSize(); i<sz; i++)
220 {
221 if (pJSContext == m_ContextArray.GetAt(i))
222 {
223 delete pJSContext;
224 m_ContextArray.RemoveAt(i);
225 break;
226 }
227 }
228}
229
230IFXJS_Context* CJS_Runtime::GetCurrentContext()
231{
232 if(!m_ContextArray.GetSize())
233 return NULL;
234 return m_ContextArray.GetAt(m_ContextArray.GetSize()-1);
235}
236
237void CJS_Runtime::SetReaderDocument(CPDFSDK_Document* pReaderDoc)
238{
239 if (m_pDocument != pReaderDoc)
240 {
241 v8::Isolate::Scope isolate_scope(m_isolate);
Bo Xufdc00a72014-10-28 23:03:33 -0700242 v8::Locker locker(m_isolate);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700243 v8::HandleScope handle_scope(m_isolate);
244 v8::Local<v8::Context> context =v8::Local<v8::Context>::New(m_isolate, m_context);
245 v8::Context::Scope context_scope(context);
246
247 m_pDocument = pReaderDoc;
248
249 if (pReaderDoc)
250 {
251 JSObject pThis = JS_GetThisObj(*this);
252 if(!pThis.IsEmpty())
253 {
254 if (JS_GetObjDefnID(pThis) == JS_GetObjDefnID(*this, L"Document"))
255 {
256 if (CJS_Document* pJSDocument = (CJS_Document*)JS_GetPrivate(pThis))
257 {
258 if (Document * pDocument = (Document*)pJSDocument->GetEmbedObject())
259 pDocument->AttachDoc(pReaderDoc);
260 }
261 }
262 }
263 JS_SetThisObj(*this, JS_GetObjDefnID(*this, L"Document"));
264 }
265 else
266 {
267 JS_SetThisObj(*this, JS_GetObjDefnID(*this, L"app"));
268 }
269 }
270}
271
272FX_BOOL CJS_Runtime::AddEventToLoop(const CFX_WideString& sTargetName, JS_EVENT_T eEventType)
273{
274 if (m_pFieldEventPath == NULL)
275 {
276 m_pFieldEventPath = new CJS_FieldEvent;
277 m_pFieldEventPath->sTargetName = sTargetName;
278 m_pFieldEventPath->eEventType = eEventType;
279 m_pFieldEventPath->pNext = NULL;
280
281 return TRUE;
282 }
283
284 //to search
285 CJS_FieldEvent* p = m_pFieldEventPath;
286 CJS_FieldEvent* pLast = m_pFieldEventPath;
287 while (p)
288 {
289 if (p->eEventType == eEventType && p->sTargetName == sTargetName)
290 return FALSE;
291
292 pLast = p;
293 p = p->pNext;
294 }
295
296 //to add
297 CJS_FieldEvent* pNew = new CJS_FieldEvent;
298 pNew->sTargetName = sTargetName;
299 pNew->eEventType = eEventType;
300 pNew->pNext = NULL;
301
302 pLast->pNext = pNew;
303
304 return TRUE;
305}
306
307void CJS_Runtime::RemoveEventInLoop(const CFX_WideString& sTargetName, JS_EVENT_T eEventType)
308{
309 FX_BOOL bFind = FALSE;
310
311 CJS_FieldEvent* p = m_pFieldEventPath;
312 CJS_FieldEvent* pLast = NULL;
313 while (p)
314 {
315 if (p->eEventType == eEventType && p->sTargetName == sTargetName)
316 {
317 bFind = TRUE;
318 break;
319 }
320
321 pLast = p;
322 p = p->pNext;
323 }
324
325 if (bFind)
326 {
327 RemoveEventsInLoop(p);
328
329 if (p == m_pFieldEventPath)
330 m_pFieldEventPath = NULL;
331
332 if (pLast)
333 pLast->pNext = NULL;
334 }
335}
336
337void CJS_Runtime::RemoveEventsInLoop(CJS_FieldEvent* pStart)
338{
339 CJS_FieldEvent* p = pStart;
340
341 while (p)
342 {
343 CJS_FieldEvent* pOld = p;
344 p = pOld->pNext;
345
346 delete pOld;
347 }
348}
349
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200350v8::Local<v8::Context> CJS_Runtime::NewJSContext()
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700351{
352 return v8::Local<v8::Context>::New(m_isolate, m_context);
353}
354
355CFX_WideString ChangeObjName(const CFX_WideString& str)
356{
357 CFX_WideString sRet = str;
Bo Xuf13c1f32014-11-14 17:03:50 -0800358 sRet.Replace(L"_", L".");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700359 return sRet;
360}
Tom Sepezca3ac5e2015-06-10 17:38:11 -0700361FX_BOOL CJS_Runtime::GetHValueByName(const CFX_ByteStringC& utf8Name, FXJSE_HVALUE hValue)
Bo Xufdc00a72014-10-28 23:03:33 -0700362{
Tom Sepezd7e5cc72015-06-10 14:33:37 -0700363 const FX_CHAR* name = utf8Name.GetCStr();
Bo Xufdc00a72014-10-28 23:03:33 -0700364
365 v8::Locker lock(GetIsolate());
366 v8::Isolate::Scope isolate_scope(GetIsolate());
367 v8::HandleScope handle_scope(GetIsolate());
368 v8::Local<v8::Context> context =
369 v8::Local<v8::Context>::New(GetIsolate(), m_context);
370 v8::Context::Scope context_scope(context);
371
372
373 //v8::Local<v8::Context> tmpCotext = v8::Local<v8::Context>::New(GetIsolate(), m_context);
374 v8::Local<v8::Value> propvalue = context->Global()->Get(v8::String::NewFromUtf8(GetIsolate(), name, v8::String::kNormalString, utf8Name.GetLength()));
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700375
Bo Xufdc00a72014-10-28 23:03:33 -0700376 if (propvalue.IsEmpty()) {
377 FXJSE_Value_SetUndefined(hValue);
378 return FALSE;
379 }
380 ((CFXJSE_Value*)hValue)->ForceSetValue(propvalue);
381
382 return TRUE;
383}
Tom Sepezca3ac5e2015-06-10 17:38:11 -0700384FX_BOOL CJS_Runtime::SetHValueByName(const CFX_ByteStringC& utf8Name, FXJSE_HVALUE hValue)
Bo Xufdc00a72014-10-28 23:03:33 -0700385{
386 if (utf8Name.IsEmpty() || hValue == NULL)
387 return FALSE;
Tom Sepezd7e5cc72015-06-10 14:33:37 -0700388 const FX_CHAR* name = utf8Name.GetCStr();
Bo Xufdc00a72014-10-28 23:03:33 -0700389 v8::Isolate* pIsolate = GetIsolate();
390 v8::Locker lock(pIsolate);
391 v8::Isolate::Scope isolate_scope(pIsolate);
392 v8::HandleScope handle_scope(pIsolate);
393 v8::Local<v8::Context> context =
394 v8::Local<v8::Context>::New(pIsolate, m_context);
395 v8::Context::Scope context_scope(context);
396
397 //v8::Local<v8::Context> tmpCotext = v8::Local<v8::Context>::New(GetIsolate(), m_context);
398 v8::Local<v8::Value> propvalue = v8::Local<v8::Value>::New(GetIsolate(),((CFXJSE_Value*)hValue)->DirectGetValue());
399 context->Global()->Set(v8::String::NewFromUtf8(pIsolate, name, v8::String::kNormalString, utf8Name.GetLength()), propvalue);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700400
Bo Xufdc00a72014-10-28 23:03:33 -0700401 return TRUE;
402}