• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
Initialize(unsigned int slot,void * isolate)39 void IJS_Runtime::Initialize(unsigned int slot, void* isolate) {
40   FXJS_Initialize(slot, reinterpret_cast<v8::Isolate*>(isolate));
41 }
42 
43 // static
Destroy()44 void IJS_Runtime::Destroy() {
45   FXJS_Release();
46 }
47 
48 // static
Create(CPDFSDK_FormFillEnvironment * pFormFillEnv)49 IJS_Runtime* IJS_Runtime::Create(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
50   return new CJS_Runtime(pFormFillEnv);
51 }
52 
53 // static
CurrentRuntimeFromIsolate(v8::Isolate * pIsolate)54 CJS_Runtime* CJS_Runtime::CurrentRuntimeFromIsolate(v8::Isolate* pIsolate) {
55   return static_cast<CJS_Runtime*>(
56       CFXJS_Engine::CurrentEngineFromIsolate(pIsolate));
57 }
58 
CJS_Runtime(CPDFSDK_FormFillEnvironment * pFormFillEnv)59 CJS_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 
~CJS_Runtime()92 CJS_Runtime::~CJS_Runtime() {
93   NotifyObservedPtrs();
94   ReleaseEngine();
95   if (m_isolateManaged) {
96     GetIsolate()->Dispose();
97     SetIsolate(nullptr);
98   }
99 }
100 
DefineJSObjects()101 void 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 
NewEventContext()149 IJS_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 
ReleaseEventContext(IJS_EventContext * pContext)155 void 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 
GetCurrentEventContext() const163 CJS_EventContext* CJS_Runtime::GetCurrentEventContext() const {
164   return m_EventContextArray.empty() ? nullptr
165                                      : m_EventContextArray.back().get();
166 }
167 
SetFormFillEnvToDocument()168 void 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 
GetFormFillEnv() const193 CPDFSDK_FormFillEnvironment* CJS_Runtime::GetFormFillEnv() const {
194   return m_pFormFillEnv.Get();
195 }
196 
ExecuteScript(const CFX_WideString & script,CFX_WideString * info)197 int 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 
AddEventToSet(const FieldEvent & event)208 bool CJS_Runtime::AddEventToSet(const FieldEvent& event) {
209   return m_FieldEventSet.insert(event).second;
210 }
211 
RemoveEventFromSet(const FieldEvent & event)212 void CJS_Runtime::RemoveEventFromSet(const FieldEvent& event) {
213   m_FieldEventSet.erase(event);
214 }
215 
216 #ifdef PDF_ENABLE_XFA
ChangeObjName(const CFX_WideString & str)217 CFX_WideString ChangeObjName(const CFX_WideString& str) {
218   CFX_WideString sRet = str;
219   sRet.Replace(L"_", L".");
220   return sRet;
221 }
GetValueByName(const CFX_ByteStringC & utf8Name,CFXJSE_Value * pValue)222 bool 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 }
SetValueByName(const CFX_ByteStringC & utf8Name,CFXJSE_Value * pValue)242 bool 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