cjs_runtime.cpp revision 5ae9d0c6fd838a2967cca72aa5751b51dadc2769
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/javascript/cjs_runtime.h" 8 9#include <algorithm> 10 11#include "fpdfsdk/cpdfsdk_formfillenvironment.h" 12#include "fpdfsdk/javascript/Annot.h" 13#include "fpdfsdk/javascript/Consts.h" 14#include "fpdfsdk/javascript/Document.h" 15#include "fpdfsdk/javascript/Field.h" 16#include "fpdfsdk/javascript/Icon.h" 17#include "fpdfsdk/javascript/JS_Define.h" 18#include "fpdfsdk/javascript/JS_EventHandler.h" 19#include "fpdfsdk/javascript/JS_GlobalData.h" 20#include "fpdfsdk/javascript/JS_Object.h" 21#include "fpdfsdk/javascript/JS_Value.h" 22#include "fpdfsdk/javascript/PublicMethods.h" 23#include "fpdfsdk/javascript/app.h" 24#include "fpdfsdk/javascript/cjs_event_context.h" 25#include "fpdfsdk/javascript/color.h" 26#include "fpdfsdk/javascript/console.h" 27#include "fpdfsdk/javascript/event.h" 28#include "fpdfsdk/javascript/global.h" 29#include "fpdfsdk/javascript/report.h" 30#include "fpdfsdk/javascript/util.h" 31#include "public/fpdf_formfill.h" 32#include "third_party/base/stl_util.h" 33 34#ifdef PDF_ENABLE_XFA 35#include "fxjs/cfxjse_value.h" 36#endif // PDF_ENABLE_XFA 37 38// static 39void IJS_Runtime::Initialize(unsigned int slot, void* isolate) { 40 FXJS_Initialize(slot, reinterpret_cast<v8::Isolate*>(isolate)); 41} 42 43// static 44void IJS_Runtime::Destroy() { 45 FXJS_Release(); 46} 47 48// static 49IJS_Runtime* IJS_Runtime::Create(CPDFSDK_FormFillEnvironment* pFormFillEnv) { 50 return new CJS_Runtime(pFormFillEnv); 51} 52 53// static 54CJS_Runtime* CJS_Runtime::CurrentRuntimeFromIsolate(v8::Isolate* pIsolate) { 55 return static_cast<CJS_Runtime*>( 56 CFXJS_Engine::CurrentEngineFromIsolate(pIsolate)); 57} 58 59CJS_Runtime::CJS_Runtime(CPDFSDK_FormFillEnvironment* pFormFillEnv) 60 : m_pFormFillEnv(pFormFillEnv), 61 m_bBlocking(false), 62 m_isolateManaged(false) { 63 v8::Isolate* pIsolate = nullptr; 64 65 IPDF_JSPLATFORM* pPlatform = m_pFormFillEnv->GetFormFillInfo()->m_pJsPlatform; 66 if (pPlatform->version <= 2) { 67 unsigned int embedderDataSlot = 0; 68 v8::Isolate* pExternalIsolate = nullptr; 69 if (pPlatform->version == 2) { 70 pExternalIsolate = reinterpret_cast<v8::Isolate*>(pPlatform->m_isolate); 71 embedderDataSlot = pPlatform->m_v8EmbedderSlot; 72 } 73 FXJS_Initialize(embedderDataSlot, pExternalIsolate); 74 } 75 m_isolateManaged = FXJS_GetIsolate(&pIsolate); 76 SetIsolate(pIsolate); 77 78#ifdef PDF_ENABLE_XFA 79 v8::Isolate::Scope isolate_scope(pIsolate); 80 v8::HandleScope handle_scope(pIsolate); 81#endif 82 83 if (m_isolateManaged || FXJS_GlobalIsolateRefCount() == 0) 84 DefineJSObjects(); 85 86 IJS_EventContext* pContext = NewEventContext(); 87 InitializeEngine(); 88 ReleaseEventContext(pContext); 89 SetFormFillEnvToDocument(); 90} 91 92CJS_Runtime::~CJS_Runtime() { 93 NotifyObservedPtrs(); 94 ReleaseEngine(); 95 if (m_isolateManaged) { 96 GetIsolate()->Dispose(); 97 SetIsolate(nullptr); 98 } 99} 100 101void CJS_Runtime::DefineJSObjects() { 102 v8::Isolate::Scope isolate_scope(GetIsolate()); 103 v8::HandleScope handle_scope(GetIsolate()); 104 v8::Local<v8::Context> context = v8::Context::New(GetIsolate()); 105 v8::Context::Scope context_scope(context); 106 107 // The call order determines the "ObjDefID" assigned to each class. 108 // ObjDefIDs 0 - 2 109 CJS_Border::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 110 CJS_Display::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 111 CJS_Font::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 112 113 // ObjDefIDs 3 - 5 114 CJS_Highlight::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 115 CJS_Position::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 116 CJS_ScaleHow::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 117 118 // ObjDefIDs 6 - 8 119 CJS_ScaleWhen::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 120 CJS_Style::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 121 CJS_Zoomtype::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 122 123 // ObjDefIDs 9 - 11 124 CJS_App::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 125 CJS_Color::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 126 CJS_Console::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 127 128 // ObjDefIDs 12 - 14 129 CJS_Document::DefineJSObjects(this, FXJSOBJTYPE_GLOBAL); 130 CJS_Event::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 131 CJS_Field::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC); 132 133 // ObjDefIDs 15 - 17 134 CJS_Global::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 135 CJS_Icon::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC); 136 CJS_Util::DefineJSObjects(this, FXJSOBJTYPE_STATIC); 137 138 // ObjDefIDs 18 - 20 (these can't fail, return void). 139 CJS_PublicMethods::DefineJSObjects(this); 140 CJS_GlobalConsts::DefineJSObjects(this); 141 CJS_GlobalArrays::DefineJSObjects(this); 142 143 // ObjDefIDs 21 - 23. 144 CJS_TimerObj::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC); 145 CJS_PrintParamsObj::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC); 146 CJS_Annot::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC); 147} 148 149IJS_EventContext* CJS_Runtime::NewEventContext() { 150 m_EventContextArray.push_back( 151 std::unique_ptr<CJS_EventContext>(new CJS_EventContext(this))); 152 return m_EventContextArray.back().get(); 153} 154 155void CJS_Runtime::ReleaseEventContext(IJS_EventContext* pContext) { 156 auto it = std::find(m_EventContextArray.begin(), m_EventContextArray.end(), 157 pdfium::FakeUniquePtr<CJS_EventContext>( 158 static_cast<CJS_EventContext*>(pContext))); 159 if (it != m_EventContextArray.end()) 160 m_EventContextArray.erase(it); 161} 162 163CJS_EventContext* CJS_Runtime::GetCurrentEventContext() const { 164 return m_EventContextArray.empty() ? nullptr 165 : m_EventContextArray.back().get(); 166} 167 168void CJS_Runtime::SetFormFillEnvToDocument() { 169 v8::Isolate::Scope isolate_scope(GetIsolate()); 170 v8::HandleScope handle_scope(GetIsolate()); 171 v8::Local<v8::Context> context = NewLocalContext(); 172 v8::Context::Scope context_scope(context); 173 174 v8::Local<v8::Object> pThis = GetThisObj(); 175 if (pThis.IsEmpty()) 176 return; 177 178 if (CFXJS_Engine::GetObjDefnID(pThis) != CJS_Document::g_nObjDefnID) 179 return; 180 181 CJS_Document* pJSDocument = 182 static_cast<CJS_Document*>(GetObjectPrivate(pThis)); 183 if (!pJSDocument) 184 return; 185 186 Document* pDocument = static_cast<Document*>(pJSDocument->GetEmbedObject()); 187 if (!pDocument) 188 return; 189 190 pDocument->SetFormFillEnv(m_pFormFillEnv.Get()); 191} 192 193CPDFSDK_FormFillEnvironment* CJS_Runtime::GetFormFillEnv() const { 194 return m_pFormFillEnv.Get(); 195} 196 197int CJS_Runtime::ExecuteScript(const CFX_WideString& script, 198 CFX_WideString* info) { 199 FXJSErr error = {}; 200 int nRet = Execute(script, &error); 201 if (nRet < 0) { 202 info->Format(L"[ Line: %05d { %s } ] : %s", error.linnum - 1, error.srcline, 203 error.message); 204 } 205 return nRet; 206} 207 208bool CJS_Runtime::AddEventToSet(const FieldEvent& event) { 209 return m_FieldEventSet.insert(event).second; 210} 211 212void CJS_Runtime::RemoveEventFromSet(const FieldEvent& event) { 213 m_FieldEventSet.erase(event); 214} 215 216#ifdef PDF_ENABLE_XFA 217CFX_WideString ChangeObjName(const CFX_WideString& str) { 218 CFX_WideString sRet = str; 219 sRet.Replace(L"_", L"."); 220 return sRet; 221} 222bool CJS_Runtime::GetValueByName(const CFX_ByteStringC& utf8Name, 223 CFXJSE_Value* pValue) { 224 const FX_CHAR* name = utf8Name.c_str(); 225 226 v8::Isolate::Scope isolate_scope(GetIsolate()); 227 v8::HandleScope handle_scope(GetIsolate()); 228 v8::Local<v8::Context> context = NewLocalContext(); 229 v8::Context::Scope context_scope(context); 230 231 v8::Local<v8::Value> propvalue = 232 context->Global()->Get(v8::String::NewFromUtf8( 233 GetIsolate(), name, v8::String::kNormalString, utf8Name.GetLength())); 234 235 if (propvalue.IsEmpty()) { 236 pValue->SetUndefined(); 237 return false; 238 } 239 pValue->ForceSetValue(propvalue); 240 return true; 241} 242bool CJS_Runtime::SetValueByName(const CFX_ByteStringC& utf8Name, 243 CFXJSE_Value* pValue) { 244 if (utf8Name.IsEmpty() || !pValue) 245 return false; 246 const FX_CHAR* name = utf8Name.c_str(); 247 v8::Isolate* pIsolate = GetIsolate(); 248 v8::Isolate::Scope isolate_scope(pIsolate); 249 v8::HandleScope handle_scope(pIsolate); 250 v8::Local<v8::Context> context = NewLocalContext(); 251 v8::Context::Scope context_scope(context); 252 253 // v8::Local<v8::Context> tmpCotext = 254 // v8::Local<v8::Context>::New(GetIsolate(), m_context); 255 v8::Local<v8::Value> propvalue = 256 v8::Local<v8::Value>::New(GetIsolate(), pValue->DirectGetValue()); 257 context->Global()->Set( 258 v8::String::NewFromUtf8(pIsolate, name, v8::String::kNormalString, 259 utf8Name.GetLength()), 260 propvalue); 261 return true; 262} 263#endif 264