blob: d8fea8d768ffc275e41f8d8714358609e6c3b140 [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"
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()
51{
52 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{
66 if(pRuntime)
67 delete (CJS_Runtime*)pRuntime;
68}
69
70CJS_GlobalData* CJS_RuntimeFactory::NewGlobalData(CPDFDoc_Environment* pApp)
71{
72 if (m_pGlobalData)
73 {
74 m_nGlobalDataCount++;
75 return m_pGlobalData;
76 }
77 else
78 {
79 m_nGlobalDataCount = 1;
80 m_pGlobalData = new CJS_GlobalData(pApp);
81 return m_pGlobalData;
82 }
83}
84
85void CJS_RuntimeFactory::ReleaseGlobalData()
86{
87 m_nGlobalDataCount--;
88
89 if (m_nGlobalDataCount <= 0)
90 {
91 delete m_pGlobalData;
92 m_pGlobalData = NULL;
93 }
94}
95
Tom Sepezd2cc1b92015-04-30 15:19:03 -070096void* CJS_ArrayBufferAllocator::Allocate(size_t length) {
97 return calloc(1, length);
98}
99
100void* CJS_ArrayBufferAllocator::AllocateUninitialized(size_t length) {
101 return malloc(length);
102}
103
104void CJS_ArrayBufferAllocator::Free(void* data, size_t length) {
105 free(data);
106}
107
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700108/* ------------------------------ CJS_Runtime ------------------------------ */
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200109extern v8::Global<v8::ObjectTemplate>& _getGlobalObjectTemplate(IJS_Runtime* pJSRuntime);
Bo Xufdc00a72014-10-28 23:03:33 -0700110CJS_Runtime::CJS_Runtime(CPDFDoc_Environment* pApp) :
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700111 m_pApp(pApp),
112 m_pDocument(NULL),
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700113 m_bBlocking(FALSE),
Tom Sepezd2cc1b92015-04-30 15:19:03 -0700114 m_bRegistered(FALSE),
115 m_pFieldEventPath(NULL)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700116{
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700117 if (CPDFXFA_App::GetInstance()->GetJSERuntime()) {
118 m_isolate = (v8::Isolate*)CPDFXFA_App::GetInstance()->GetJSERuntime();
Tom Sepezd2cc1b92015-04-30 15:19:03 -0700119 } else {
120 m_pArrayBufferAllocator.reset(new CJS_ArrayBufferAllocator());
121 v8::Isolate::CreateParams params;
122 params.array_buffer_allocator = m_pArrayBufferAllocator.get();
123 m_isolate = v8::Isolate::New(params);
124 }
125
Bo Xufdc00a72014-10-28 23:03:33 -0700126 v8::Isolate* isolate = m_isolate;
127 v8::Isolate::Scope isolate_scope(isolate);
128 v8::Locker locker(isolate);
129 v8::HandleScope handle_scope(isolate);
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700130 if (CPDFXFA_App::GetInstance()->InitRuntime(FALSE)) {
Bo Xufdc00a72014-10-28 23:03:33 -0700131 CJS_Context * pContext = (CJS_Context*)NewContext();
132 JS_InitialRuntime(*this, this, pContext, m_context);
133 ReleaseContext(pContext);
134 return;
135 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700136
137 InitJSObjects();
138
139 CJS_Context * pContext = (CJS_Context*)NewContext();
140 JS_InitialRuntime(*this, this, pContext, m_context);
141 ReleaseContext(pContext);
142}
143
144CJS_Runtime::~CJS_Runtime()
145{
Bo Xufdc00a72014-10-28 23:03:33 -0700146 int size = m_ContextArray.GetSize();
147 for (int i=0;i < size; i++)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700148 delete m_ContextArray.GetAt(i);
149
150 m_ContextArray.RemoveAll();
151
Bo Xufdc00a72014-10-28 23:03:33 -0700152 //JS_ReleaseRuntime(*this, m_context);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700153
154 RemoveEventsInLoop(m_pFieldEventPath);
155
156 m_pApp = NULL;
157 m_pDocument = NULL;
158 m_pFieldEventPath = NULL;
159 m_context.Reset();
160
161 //m_isolate->Exit();
Bo Xufdc00a72014-10-28 23:03:33 -0700162 //m_isolate->Dispose();
163 m_isolate = NULL;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700164}
165
166FX_BOOL CJS_Runtime::InitJSObjects()
167{
168 v8::Isolate::Scope isolate_scope(GetIsolate());
Bo Xufdc00a72014-10-28 23:03:33 -0700169 v8::Locker locker(GetIsolate());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700170 v8::HandleScope handle_scope(GetIsolate());
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200171 v8::Local<v8::Context> context = v8::Context::New(GetIsolate());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700172 v8::Context::Scope context_scope(context);
173 //0 - 8
174 if (CJS_Border::Init(*this, JS_STATIC) < 0) return FALSE;
175 if (CJS_Display::Init(*this, JS_STATIC) < 0) return FALSE;
176 if (CJS_Font::Init(*this, JS_STATIC) < 0) return FALSE;
177 if (CJS_Highlight::Init(*this, JS_STATIC) < 0) return FALSE;
178 if (CJS_Position::Init(*this, JS_STATIC) < 0) return FALSE;
179 if (CJS_ScaleHow::Init(*this, JS_STATIC) < 0) return FALSE;
180 if (CJS_ScaleWhen::Init(*this, JS_STATIC) < 0) return FALSE;
181 if (CJS_Style::Init(*this, JS_STATIC) < 0) return FALSE;
182 if (CJS_Zoomtype::Init(*this, JS_STATIC) < 0) return FALSE;
183
184 //9 - 11
185 if (CJS_App::Init(*this, JS_STATIC) < 0) return FALSE;
186 if (CJS_Color::Init(*this, JS_STATIC) < 0) return FALSE;
187 if (CJS_Console::Init(*this, JS_STATIC) < 0) return FALSE;
188
189 //12 - 14
190 if (CJS_Document::Init(*this, JS_DYNAMIC) < 0) return FALSE;
191 if (CJS_Event::Init(*this, JS_STATIC) < 0) return FALSE;
192 if (CJS_Field::Init(*this, JS_DYNAMIC) < 0) return FALSE;
193
194 //15 - 17
195 if (CJS_Global::Init(*this, JS_STATIC) < 0) return FALSE;
196 if (CJS_Icon::Init(*this, JS_DYNAMIC) < 0) return FALSE;
197 if (CJS_Util::Init(*this, JS_STATIC) < 0) return FALSE;
198
199 if (CJS_PublicMethods::Init(*this) < 0) return FALSE;
200 if (CJS_GlobalConsts::Init(*this) < 0) return FALSE;
201 if (CJS_GlobalArrays::Init(*this) < 0) return FALSE;
202
203 if (CJS_TimerObj::Init(*this, JS_DYNAMIC) < 0) return FALSE;
204 if (CJS_PrintParamsObj::Init(*this, JS_DYNAMIC) <0) return FALSE;
205
206 return TRUE;
207}
208
209IFXJS_Context* CJS_Runtime::NewContext()
210{
211 CJS_Context * p = new CJS_Context(this);
212 m_ContextArray.Add(p);
213 return p;
214}
215
216void CJS_Runtime::ReleaseContext(IFXJS_Context * pContext)
217{
218 CJS_Context* pJSContext = (CJS_Context*)pContext;
219
220 for (int i=0, sz=m_ContextArray.GetSize(); i<sz; i++)
221 {
222 if (pJSContext == m_ContextArray.GetAt(i))
223 {
224 delete pJSContext;
225 m_ContextArray.RemoveAt(i);
226 break;
227 }
228 }
229}
230
231IFXJS_Context* CJS_Runtime::GetCurrentContext()
232{
233 if(!m_ContextArray.GetSize())
234 return NULL;
235 return m_ContextArray.GetAt(m_ContextArray.GetSize()-1);
236}
237
238void CJS_Runtime::SetReaderDocument(CPDFSDK_Document* pReaderDoc)
239{
240 if (m_pDocument != pReaderDoc)
241 {
242 v8::Isolate::Scope isolate_scope(m_isolate);
Bo Xufdc00a72014-10-28 23:03:33 -0700243 v8::Locker locker(m_isolate);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700244 v8::HandleScope handle_scope(m_isolate);
245 v8::Local<v8::Context> context =v8::Local<v8::Context>::New(m_isolate, m_context);
246 v8::Context::Scope context_scope(context);
247
248 m_pDocument = pReaderDoc;
249
250 if (pReaderDoc)
251 {
252 JSObject pThis = JS_GetThisObj(*this);
253 if(!pThis.IsEmpty())
254 {
255 if (JS_GetObjDefnID(pThis) == JS_GetObjDefnID(*this, L"Document"))
256 {
257 if (CJS_Document* pJSDocument = (CJS_Document*)JS_GetPrivate(pThis))
258 {
259 if (Document * pDocument = (Document*)pJSDocument->GetEmbedObject())
260 pDocument->AttachDoc(pReaderDoc);
261 }
262 }
263 }
264 JS_SetThisObj(*this, JS_GetObjDefnID(*this, L"Document"));
265 }
266 else
267 {
268 JS_SetThisObj(*this, JS_GetObjDefnID(*this, L"app"));
269 }
270 }
271}
272
273FX_BOOL CJS_Runtime::AddEventToLoop(const CFX_WideString& sTargetName, JS_EVENT_T eEventType)
274{
275 if (m_pFieldEventPath == NULL)
276 {
277 m_pFieldEventPath = new CJS_FieldEvent;
278 m_pFieldEventPath->sTargetName = sTargetName;
279 m_pFieldEventPath->eEventType = eEventType;
280 m_pFieldEventPath->pNext = NULL;
281
282 return TRUE;
283 }
284
285 //to search
286 CJS_FieldEvent* p = m_pFieldEventPath;
287 CJS_FieldEvent* pLast = m_pFieldEventPath;
288 while (p)
289 {
290 if (p->eEventType == eEventType && p->sTargetName == sTargetName)
291 return FALSE;
292
293 pLast = p;
294 p = p->pNext;
295 }
296
297 //to add
298 CJS_FieldEvent* pNew = new CJS_FieldEvent;
299 pNew->sTargetName = sTargetName;
300 pNew->eEventType = eEventType;
301 pNew->pNext = NULL;
302
303 pLast->pNext = pNew;
304
305 return TRUE;
306}
307
308void CJS_Runtime::RemoveEventInLoop(const CFX_WideString& sTargetName, JS_EVENT_T eEventType)
309{
310 FX_BOOL bFind = FALSE;
311
312 CJS_FieldEvent* p = m_pFieldEventPath;
313 CJS_FieldEvent* pLast = NULL;
314 while (p)
315 {
316 if (p->eEventType == eEventType && p->sTargetName == sTargetName)
317 {
318 bFind = TRUE;
319 break;
320 }
321
322 pLast = p;
323 p = p->pNext;
324 }
325
326 if (bFind)
327 {
328 RemoveEventsInLoop(p);
329
330 if (p == m_pFieldEventPath)
331 m_pFieldEventPath = NULL;
332
333 if (pLast)
334 pLast->pNext = NULL;
335 }
336}
337
338void CJS_Runtime::RemoveEventsInLoop(CJS_FieldEvent* pStart)
339{
340 CJS_FieldEvent* p = pStart;
341
342 while (p)
343 {
344 CJS_FieldEvent* pOld = p;
345 p = pOld->pNext;
346
347 delete pOld;
348 }
349}
350
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200351v8::Local<v8::Context> CJS_Runtime::NewJSContext()
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700352{
353 return v8::Local<v8::Context>::New(m_isolate, m_context);
354}
355
356CFX_WideString ChangeObjName(const CFX_WideString& str)
357{
358 CFX_WideString sRet = str;
Bo Xuf13c1f32014-11-14 17:03:50 -0800359 sRet.Replace(L"_", L".");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700360 return sRet;
361}
Tom Sepezca3ac5e2015-06-10 17:38:11 -0700362FX_BOOL CJS_Runtime::GetHValueByName(const CFX_ByteStringC& utf8Name, FXJSE_HVALUE hValue)
Bo Xufdc00a72014-10-28 23:03:33 -0700363{
Tom Sepezd7e5cc72015-06-10 14:33:37 -0700364 const FX_CHAR* name = utf8Name.GetCStr();
Bo Xufdc00a72014-10-28 23:03:33 -0700365
366 v8::Locker lock(GetIsolate());
367 v8::Isolate::Scope isolate_scope(GetIsolate());
368 v8::HandleScope handle_scope(GetIsolate());
369 v8::Local<v8::Context> context =
370 v8::Local<v8::Context>::New(GetIsolate(), m_context);
371 v8::Context::Scope context_scope(context);
372
373
374 //v8::Local<v8::Context> tmpCotext = v8::Local<v8::Context>::New(GetIsolate(), m_context);
375 v8::Local<v8::Value> propvalue = context->Global()->Get(v8::String::NewFromUtf8(GetIsolate(), name, v8::String::kNormalString, utf8Name.GetLength()));
376
377 if (propvalue.IsEmpty()) {
378 FXJSE_Value_SetUndefined(hValue);
379 return FALSE;
380 }
381 ((CFXJSE_Value*)hValue)->ForceSetValue(propvalue);
382
383 return TRUE;
384}
Tom Sepezca3ac5e2015-06-10 17:38:11 -0700385FX_BOOL CJS_Runtime::SetHValueByName(const CFX_ByteStringC& utf8Name, FXJSE_HVALUE hValue)
Bo Xufdc00a72014-10-28 23:03:33 -0700386{
387 if (utf8Name.IsEmpty() || hValue == NULL)
388 return FALSE;
Tom Sepezd7e5cc72015-06-10 14:33:37 -0700389 const FX_CHAR* name = utf8Name.GetCStr();
Bo Xufdc00a72014-10-28 23:03:33 -0700390 v8::Isolate* pIsolate = GetIsolate();
391 v8::Locker lock(pIsolate);
392 v8::Isolate::Scope isolate_scope(pIsolate);
393 v8::HandleScope handle_scope(pIsolate);
394 v8::Local<v8::Context> context =
395 v8::Local<v8::Context>::New(pIsolate, m_context);
396 v8::Context::Scope context_scope(context);
397
398 //v8::Local<v8::Context> tmpCotext = v8::Local<v8::Context>::New(GetIsolate(), m_context);
399 v8::Local<v8::Value> propvalue = v8::Local<v8::Value>::New(GetIsolate(),((CFXJSE_Value*)hValue)->DirectGetValue());
400 context->Global()->Set(v8::String::NewFromUtf8(pIsolate, name, v8::String::kNormalString, utf8Name.GetLength()), propvalue);
401
402 return TRUE;
403}