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