| OLD | NEW | 
|---|
|  | (Empty) | 
| 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 "fpdfsdk/src/javascript/JS_Runtime.h" |  | 
| 8 |  | 
| 9 #include "fpdfsdk/include/fsdk_mgr.h"  // For CPDFDoc_Environment. |  | 
| 10 #include "fpdfsdk/include/javascript/IJavaScript.h" |  | 
| 11 #include "fpdfsdk/src/javascript/Consts.h" |  | 
| 12 #include "fpdfsdk/src/javascript/Document.h" |  | 
| 13 #include "fpdfsdk/src/javascript/Field.h" |  | 
| 14 #include "fpdfsdk/src/javascript/Icon.h" |  | 
| 15 #include "fpdfsdk/src/javascript/JS_Context.h" |  | 
| 16 #include "fpdfsdk/src/javascript/JS_Define.h" |  | 
| 17 #include "fpdfsdk/src/javascript/JS_EventHandler.h" |  | 
| 18 #include "fpdfsdk/src/javascript/JS_GlobalData.h" |  | 
| 19 #include "fpdfsdk/src/javascript/JS_Object.h" |  | 
| 20 #include "fpdfsdk/src/javascript/JS_Value.h" |  | 
| 21 #include "fpdfsdk/src/javascript/PublicMethods.h" |  | 
| 22 #include "fpdfsdk/src/javascript/app.h" |  | 
| 23 #include "fpdfsdk/src/javascript/color.h" |  | 
| 24 #include "fpdfsdk/src/javascript/console.h" |  | 
| 25 #include "fpdfsdk/src/javascript/event.h" |  | 
| 26 #include "fpdfsdk/src/javascript/global.h" |  | 
| 27 #include "fpdfsdk/src/javascript/report.h" |  | 
| 28 #include "fpdfsdk/src/javascript/util.h" |  | 
| 29 #include "third_party/base/stl_util.h" |  | 
| 30 |  | 
| 31 #ifdef PDF_ENABLE_XFA |  | 
| 32 #include "fpdfsdk/include/fpdfxfa/fpdfxfa_app.h" |  | 
| 33 #include "xfa/src/fxjse/value.h" |  | 
| 34 #endif  // PDF_ENABLE_XFA |  | 
| 35 |  | 
| 36 // static |  | 
| 37 void IJS_Runtime::Initialize(unsigned int slot, void* isolate) { |  | 
| 38   FXJS_Initialize(slot, reinterpret_cast<v8::Isolate*>(isolate)); |  | 
| 39 } |  | 
| 40 |  | 
| 41 // static |  | 
| 42 IJS_Runtime* IJS_Runtime::Create(CPDFDoc_Environment* pEnv) { |  | 
| 43   return new CJS_Runtime(pEnv); |  | 
| 44 } |  | 
| 45 |  | 
| 46 // static |  | 
| 47 CJS_Runtime* CJS_Runtime::FromContext(const IJS_Context* cc) { |  | 
| 48   const CJS_Context* pContext = static_cast<const CJS_Context*>(cc); |  | 
| 49   return pContext->GetJSRuntime(); |  | 
| 50 } |  | 
| 51 |  | 
| 52 CJS_Runtime::CJS_Runtime(CPDFDoc_Environment* pApp) |  | 
| 53     : m_pApp(pApp), |  | 
| 54       m_pDocument(NULL), |  | 
| 55       m_bBlocking(FALSE), |  | 
| 56       m_isolate(NULL), |  | 
| 57       m_isolateManaged(false) { |  | 
| 58 #ifndef PDF_ENABLE_XFA |  | 
| 59   IPDF_JSPLATFORM* pPlatform = m_pApp->GetFormFillInfo()->m_pJsPlatform; |  | 
| 60   if (pPlatform->version <= 2) { |  | 
| 61     unsigned int embedderDataSlot = 0; |  | 
| 62     v8::Isolate* pExternalIsolate = nullptr; |  | 
| 63     if (pPlatform->version == 2) { |  | 
| 64       pExternalIsolate = reinterpret_cast<v8::Isolate*>(pPlatform->m_isolate); |  | 
| 65       embedderDataSlot = pPlatform->m_v8EmbedderSlot; |  | 
| 66 #else |  | 
| 67   if (CPDFXFA_App::GetInstance()->GetJSERuntime()) { |  | 
| 68     // TODO(tsepez): CPDFXFA_App should also use the embedder provided isolate. |  | 
| 69     m_isolate = (v8::Isolate*)CPDFXFA_App::GetInstance()->GetJSERuntime(); |  | 
| 70   } else { |  | 
| 71     IPDF_JSPLATFORM* pPlatform = m_pApp->GetFormFillInfo()->m_pJsPlatform; |  | 
| 72     if (pPlatform->version <= 2) { |  | 
| 73       unsigned int embedderDataSlot = 0; |  | 
| 74       v8::Isolate* pExternalIsolate = nullptr; |  | 
| 75       if (pPlatform->version == 2) { |  | 
| 76         pExternalIsolate = reinterpret_cast<v8::Isolate*>(pPlatform->m_isolate); |  | 
| 77         embedderDataSlot = pPlatform->m_v8EmbedderSlot; |  | 
| 78       } |  | 
| 79       FXJS_Initialize(embedderDataSlot, pExternalIsolate); |  | 
| 80 #endif |  | 
| 81     } |  | 
| 82 #ifndef PDF_ENABLE_XFA |  | 
| 83     FXJS_Initialize(embedderDataSlot, pExternalIsolate); |  | 
| 84 #else |  | 
| 85     m_isolateManaged = FXJS_GetIsolate(&m_isolate); |  | 
| 86   } |  | 
| 87 |  | 
| 88   v8::Isolate* isolate = m_isolate; |  | 
| 89   v8::Isolate::Scope isolate_scope(isolate); |  | 
| 90   v8::Locker locker(isolate); |  | 
| 91   v8::HandleScope handle_scope(isolate); |  | 
| 92   if (CPDFXFA_App::GetInstance()->IsJavaScriptInitialized()) { |  | 
| 93     CJS_Context* pContext = (CJS_Context*)NewContext(); |  | 
| 94     FXJS_InitializeRuntime(GetIsolate(), this, &m_context, &m_StaticObjects); |  | 
| 95     ReleaseContext(pContext); |  | 
| 96     return; |  | 
| 97 #endif |  | 
| 98   } |  | 
| 99 #ifndef PDF_ENABLE_XFA |  | 
| 100   m_isolateManaged = FXJS_GetIsolate(&m_isolate); |  | 
| 101 #else |  | 
| 102 |  | 
| 103 #endif |  | 
| 104   if (m_isolateManaged || FXJS_GlobalIsolateRefCount() == 0) |  | 
| 105     DefineJSObjects(); |  | 
| 106 |  | 
| 107 #ifdef PDF_ENABLE_XFA |  | 
| 108   CPDFXFA_App::GetInstance()->SetJavaScriptInitialized(TRUE); |  | 
| 109 |  | 
| 110 #endif |  | 
| 111   CJS_Context* pContext = (CJS_Context*)NewContext(); |  | 
| 112   FXJS_InitializeRuntime(GetIsolate(), this, &m_context, &m_StaticObjects); |  | 
| 113   ReleaseContext(pContext); |  | 
| 114 } |  | 
| 115 |  | 
| 116 CJS_Runtime::~CJS_Runtime() { |  | 
| 117   for (auto* obs : m_observers) |  | 
| 118     obs->OnDestroyed(); |  | 
| 119 |  | 
| 120   for (int i = 0, sz = m_ContextArray.GetSize(); i < sz; i++) |  | 
| 121     delete m_ContextArray.GetAt(i); |  | 
| 122 |  | 
| 123   m_ContextArray.RemoveAll(); |  | 
| 124   m_ConstArrays.clear(); |  | 
| 125   FXJS_ReleaseRuntime(GetIsolate(), &m_context, &m_StaticObjects); |  | 
| 126 |  | 
| 127   m_pApp = NULL; |  | 
| 128   m_pDocument = NULL; |  | 
| 129   m_context.Reset(); |  | 
| 130 |  | 
| 131   if (m_isolateManaged) |  | 
| 132     m_isolate->Dispose(); |  | 
| 133 } |  | 
| 134 |  | 
| 135 void CJS_Runtime::DefineJSObjects() { |  | 
| 136   v8::Isolate::Scope isolate_scope(GetIsolate()); |  | 
| 137 #ifdef PDF_ENABLE_XFA |  | 
| 138   v8::Locker locker(GetIsolate()); |  | 
| 139 #endif |  | 
| 140   v8::HandleScope handle_scope(GetIsolate()); |  | 
| 141   v8::Local<v8::Context> context = v8::Context::New(GetIsolate()); |  | 
| 142   v8::Context::Scope context_scope(context); |  | 
| 143 |  | 
| 144   // The call order determines the "ObjDefID" assigned to each class. |  | 
| 145   // ObjDefIDs 0 - 2 |  | 
| 146   CJS_Border::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 147   CJS_Display::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 148   CJS_Font::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 149 |  | 
| 150   // ObjDefIDs 3 - 5 |  | 
| 151   CJS_Highlight::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 152   CJS_Position::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 153   CJS_ScaleHow::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 154 |  | 
| 155   // ObjDefIDs 6 - 8 |  | 
| 156   CJS_ScaleWhen::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 157   CJS_Style::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 158   CJS_Zoomtype::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 159 |  | 
| 160   // ObjDefIDs 9 - 11 |  | 
| 161   CJS_App::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 162   CJS_Color::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 163   CJS_Console::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 164 |  | 
| 165   // ObjDefIDs 12 - 14 |  | 
| 166   CJS_Document::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_GLOBAL); |  | 
| 167   CJS_Event::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 168   CJS_Field::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_DYNAMIC); |  | 
| 169 |  | 
| 170   // ObjDefIDs 15 - 17 |  | 
| 171   CJS_Global::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 172   CJS_Icon::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_DYNAMIC); |  | 
| 173   CJS_Util::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_STATIC); |  | 
| 174 |  | 
| 175   // ObjDefIDs 18 - 20 (these can't fail, return void). |  | 
| 176   CJS_PublicMethods::DefineJSObjects(GetIsolate()); |  | 
| 177   CJS_GlobalConsts::DefineJSObjects(this); |  | 
| 178   CJS_GlobalArrays::DefineJSObjects(this); |  | 
| 179 |  | 
| 180   // ObjDefIDs 21 - 22. |  | 
| 181   CJS_TimerObj::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_DYNAMIC); |  | 
| 182   CJS_PrintParamsObj::DefineJSObjects(GetIsolate(), FXJSOBJTYPE_DYNAMIC); |  | 
| 183 } |  | 
| 184 |  | 
| 185 IJS_Context* CJS_Runtime::NewContext() { |  | 
| 186   CJS_Context* p = new CJS_Context(this); |  | 
| 187   m_ContextArray.Add(p); |  | 
| 188   return p; |  | 
| 189 } |  | 
| 190 |  | 
| 191 void CJS_Runtime::ReleaseContext(IJS_Context* pContext) { |  | 
| 192   CJS_Context* pJSContext = (CJS_Context*)pContext; |  | 
| 193 |  | 
| 194   for (int i = 0, sz = m_ContextArray.GetSize(); i < sz; i++) { |  | 
| 195     if (pJSContext == m_ContextArray.GetAt(i)) { |  | 
| 196       delete pJSContext; |  | 
| 197       m_ContextArray.RemoveAt(i); |  | 
| 198       break; |  | 
| 199     } |  | 
| 200   } |  | 
| 201 } |  | 
| 202 |  | 
| 203 IJS_Context* CJS_Runtime::GetCurrentContext() { |  | 
| 204   if (!m_ContextArray.GetSize()) |  | 
| 205     return NULL; |  | 
| 206   return m_ContextArray.GetAt(m_ContextArray.GetSize() - 1); |  | 
| 207 } |  | 
| 208 |  | 
| 209 void CJS_Runtime::SetReaderDocument(CPDFSDK_Document* pReaderDoc) { |  | 
| 210   if (m_pDocument != pReaderDoc) { |  | 
| 211     v8::Isolate::Scope isolate_scope(m_isolate); |  | 
| 212 #ifdef PDF_ENABLE_XFA |  | 
| 213     v8::Locker locker(m_isolate); |  | 
| 214 #endif |  | 
| 215     v8::HandleScope handle_scope(m_isolate); |  | 
| 216     v8::Local<v8::Context> context = |  | 
| 217         v8::Local<v8::Context>::New(m_isolate, m_context); |  | 
| 218     v8::Context::Scope context_scope(context); |  | 
| 219 |  | 
| 220     m_pDocument = pReaderDoc; |  | 
| 221     if (pReaderDoc) { |  | 
| 222       v8::Local<v8::Object> pThis = FXJS_GetThisObj(GetIsolate()); |  | 
| 223       if (!pThis.IsEmpty()) { |  | 
| 224         if (FXJS_GetObjDefnID(pThis) == CJS_Document::g_nObjDefnID) { |  | 
| 225           if (CJS_Document* pJSDocument = |  | 
| 226                   (CJS_Document*)FXJS_GetPrivate(GetIsolate(), pThis)) { |  | 
| 227             if (Document* pDocument = (Document*)pJSDocument->GetEmbedObject()) |  | 
| 228               pDocument->AttachDoc(pReaderDoc); |  | 
| 229           } |  | 
| 230         } |  | 
| 231       } |  | 
| 232     } |  | 
| 233   } |  | 
| 234 } |  | 
| 235 |  | 
| 236 int CJS_Runtime::Execute(IJS_Context* cc, |  | 
| 237                          const wchar_t* script, |  | 
| 238                          CFX_WideString* info) { |  | 
| 239   FXJSErr error = {}; |  | 
| 240   int nRet = FXJS_Execute(m_isolate, cc, script, &error); |  | 
| 241   if (nRet < 0) { |  | 
| 242     info->Format(L"[ Line: %05d { %s } ] : %s", error.linnum - 1, error.srcline, |  | 
| 243                  error.message); |  | 
| 244   } |  | 
| 245   return nRet; |  | 
| 246 } |  | 
| 247 |  | 
| 248 bool CJS_Runtime::AddEventToSet(const FieldEvent& event) { |  | 
| 249   return m_FieldEventSet.insert(event).second; |  | 
| 250 } |  | 
| 251 |  | 
| 252 void CJS_Runtime::RemoveEventFromSet(const FieldEvent& event) { |  | 
| 253   m_FieldEventSet.erase(event); |  | 
| 254 } |  | 
| 255 |  | 
| 256 v8::Local<v8::Context> CJS_Runtime::NewJSContext() { |  | 
| 257   return v8::Local<v8::Context>::New(m_isolate, m_context); |  | 
| 258 } |  | 
| 259 |  | 
| 260 void CJS_Runtime::SetConstArray(const CFX_WideString& name, |  | 
| 261                                 v8::Local<v8::Array> array) { |  | 
| 262   m_ConstArrays[name] = v8::Global<v8::Array>(m_isolate, array); |  | 
| 263 } |  | 
| 264 |  | 
| 265 v8::Local<v8::Array> CJS_Runtime::GetConstArray(const CFX_WideString& name) { |  | 
| 266   return v8::Local<v8::Array>::New(m_isolate, m_ConstArrays[name]); |  | 
| 267 } |  | 
| 268 |  | 
| 269 #ifdef PDF_ENABLE_XFA |  | 
| 270 CFX_WideString ChangeObjName(const CFX_WideString& str) { |  | 
| 271   CFX_WideString sRet = str; |  | 
| 272   sRet.Replace(L"_", L"."); |  | 
| 273   return sRet; |  | 
| 274 } |  | 
| 275 FX_BOOL CJS_Runtime::GetHValueByName(const CFX_ByteStringC& utf8Name, |  | 
| 276                                      FXJSE_HVALUE hValue) { |  | 
| 277 #ifdef PDF_ENABLE_XFA |  | 
| 278   const FX_CHAR* name = utf8Name.GetCStr(); |  | 
| 279 |  | 
| 280   v8::Locker lock(GetIsolate()); |  | 
| 281   v8::Isolate::Scope isolate_scope(GetIsolate()); |  | 
| 282   v8::HandleScope handle_scope(GetIsolate()); |  | 
| 283   v8::Local<v8::Context> old_context = GetIsolate()->GetCurrentContext(); |  | 
| 284   v8::Local<v8::Context> context = |  | 
| 285       v8::Local<v8::Context>::New(GetIsolate(), m_context); |  | 
| 286   v8::Context::Scope context_scope(context); |  | 
| 287 |  | 
| 288   // Caution: We're about to hand to XFA an object that in order to invoke |  | 
| 289   // methods will require that the current v8::Context always has a pointer |  | 
| 290   // to a CJS_Runtime in its embedder data slot. Unfortunately, XFA creates |  | 
| 291   // its own v8::Context which has not initialized the embedder data slot. |  | 
| 292   // Do so now. |  | 
| 293   // TODO(tsepez): redesign PDF-side objects to not rely on v8::Context's |  | 
| 294   // embedder data slots, and/or to always use the right context. |  | 
| 295   FXJS_SetRuntimeForV8Context(old_context, this); |  | 
| 296 |  | 
| 297   v8::Local<v8::Value> propvalue = |  | 
| 298       context->Global()->Get(v8::String::NewFromUtf8( |  | 
| 299           GetIsolate(), name, v8::String::kNormalString, utf8Name.GetLength())); |  | 
| 300 |  | 
| 301   if (propvalue.IsEmpty()) { |  | 
| 302     FXJSE_Value_SetUndefined(hValue); |  | 
| 303     return FALSE; |  | 
| 304   } |  | 
| 305   ((CFXJSE_Value*)hValue)->ForceSetValue(propvalue); |  | 
| 306 #endif |  | 
| 307 |  | 
| 308   return TRUE; |  | 
| 309 } |  | 
| 310 FX_BOOL CJS_Runtime::SetHValueByName(const CFX_ByteStringC& utf8Name, |  | 
| 311                                      FXJSE_HVALUE hValue) { |  | 
| 312 #ifdef PDF_ENABLE_XFA |  | 
| 313   if (utf8Name.IsEmpty() || hValue == NULL) |  | 
| 314     return FALSE; |  | 
| 315   const FX_CHAR* name = utf8Name.GetCStr(); |  | 
| 316   v8::Isolate* pIsolate = GetIsolate(); |  | 
| 317   v8::Locker lock(pIsolate); |  | 
| 318   v8::Isolate::Scope isolate_scope(pIsolate); |  | 
| 319   v8::HandleScope handle_scope(pIsolate); |  | 
| 320   v8::Local<v8::Context> context = |  | 
| 321       v8::Local<v8::Context>::New(pIsolate, m_context); |  | 
| 322   v8::Context::Scope context_scope(context); |  | 
| 323 |  | 
| 324   // v8::Local<v8::Context> tmpCotext = |  | 
| 325   // v8::Local<v8::Context>::New(GetIsolate(), m_context); |  | 
| 326   v8::Local<v8::Value> propvalue = v8::Local<v8::Value>::New( |  | 
| 327       GetIsolate(), ((CFXJSE_Value*)hValue)->DirectGetValue()); |  | 
| 328   context->Global()->Set( |  | 
| 329       v8::String::NewFromUtf8(pIsolate, name, v8::String::kNormalString, |  | 
| 330                               utf8Name.GetLength()), |  | 
| 331       propvalue); |  | 
| 332 #endif |  | 
| 333   return TRUE; |  | 
| 334 } |  | 
| 335 |  | 
| 336 #endif |  | 
| 337 void CJS_Runtime::AddObserver(Observer* observer) { |  | 
| 338   ASSERT(!pdfium::ContainsKey(m_observers, observer)); |  | 
| 339   m_observers.insert(observer); |  | 
| 340 } |  | 
| 341 |  | 
| 342 void CJS_Runtime::RemoveObserver(Observer* observer) { |  | 
| 343   ASSERT(pdfium::ContainsKey(m_observers, observer)); |  | 
| 344   m_observers.erase(observer); |  | 
| 345 } |  | 
| OLD | NEW | 
|---|