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