• 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 // FXJS_V8 is a layer that makes it easier to define native objects in V8, but
8 // has no knowledge of PDF-specific native objects. It could in theory be used
9 // to implement other sets of native objects.
10 
11 // PDFium code should include this file rather than including V8 headers
12 // directly.
13 
14 #ifndef FXJS_FXJS_V8_H_
15 #define FXJS_FXJS_V8_H_
16 
17 #include <v8-util.h>
18 #include <v8.h>
19 
20 #include <map>
21 #include <memory>
22 #include <vector>
23 
24 #include "core/fxcrt/fx_string.h"
25 #ifdef PDF_ENABLE_XFA
26 // Header for CFXJSE_RuntimeData. FXJS_V8 doesn't interpret this class,
27 // it is just passed along to XFA.
28 #include "fxjs/cfxjse_runtimedata.h"
29 #endif  // PDF_ENABLE_XFA
30 
31 class CFXJS_Engine;
32 class CFXJS_ObjDefinition;
33 
34 // FXJS_V8 places no restrictions on this class; it merely passes it
35 // on to caller-provided methods.
36 class IJS_EventContext;  // A description of the event that caused JS execution.
37 
38 enum FXJSOBJTYPE {
39   FXJSOBJTYPE_DYNAMIC = 0,  // Created by native method and returned to JS.
40   FXJSOBJTYPE_STATIC,       // Created by init and hung off of global object.
41   FXJSOBJTYPE_GLOBAL,       // The global object itself (may only appear once).
42 };
43 
44 struct FXJSErr {
45   const wchar_t* message;
46   const wchar_t* srcline;
47   unsigned linnum;
48 };
49 
50 // Global weak map to save dynamic objects.
51 class V8TemplateMapTraits : public v8::StdMapTraits<void*, v8::Object> {
52  public:
53   typedef v8::GlobalValueMap<void*, v8::Object, V8TemplateMapTraits> MapType;
54   typedef void WeakCallbackDataType;
55 
WeakCallbackParameter(MapType * map,void * key,const v8::Local<v8::Object> & value)56   static WeakCallbackDataType* WeakCallbackParameter(
57       MapType* map,
58       void* key,
59       const v8::Local<v8::Object>& value) {
60     return key;
61   }
62   static MapType* MapFromWeakCallbackInfo(
63       const v8::WeakCallbackInfo<WeakCallbackDataType>&);
64 
KeyFromWeakCallbackInfo(const v8::WeakCallbackInfo<WeakCallbackDataType> & data)65   static void* KeyFromWeakCallbackInfo(
66       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
67     return data.GetParameter();
68   }
69   static const v8::PersistentContainerCallbackType kCallbackType =
70       v8::kWeakWithInternalFields;
DisposeWeak(const v8::WeakCallbackInfo<WeakCallbackDataType> & data)71   static void DisposeWeak(
72       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {}
OnWeakCallback(const v8::WeakCallbackInfo<WeakCallbackDataType> & data)73   static void OnWeakCallback(
74       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {}
75   static void Dispose(v8::Isolate* isolate,
76                       v8::Global<v8::Object> value,
77                       void* key);
DisposeCallbackData(WeakCallbackDataType * callbackData)78   static void DisposeCallbackData(WeakCallbackDataType* callbackData) {}
79 };
80 
81 class V8TemplateMap {
82  public:
83   typedef v8::GlobalValueMap<void*, v8::Object, V8TemplateMapTraits> MapType;
84 
85   explicit V8TemplateMap(v8::Isolate* isolate);
86   ~V8TemplateMap();
87 
88   void set(void* key, v8::Local<v8::Object> handle);
89 
90   friend class V8TemplateMapTraits;
91 
92  private:
93   MapType m_map;
94 };
95 
96 class FXJS_PerIsolateData {
97  public:
98   ~FXJS_PerIsolateData();
99 
100   static void SetUp(v8::Isolate* pIsolate);
101   static FXJS_PerIsolateData* Get(v8::Isolate* pIsolate);
102 
103   std::vector<std::unique_ptr<CFXJS_ObjDefinition>> m_ObjectDefnArray;
104 #ifdef PDF_ENABLE_XFA
105   std::unique_ptr<CFXJSE_RuntimeData> m_pFXJSERuntimeData;
106 #endif  // PDF_ENABLE_XFA
107   std::unique_ptr<V8TemplateMap> m_pDynamicObjsMap;
108 
109  protected:
110   explicit FXJS_PerIsolateData(v8::Isolate* pIsolate);
111 };
112 
113 class FXJS_ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
114   void* Allocate(size_t length) override;
115   void* AllocateUninitialized(size_t length) override;
116   void Free(void* data, size_t length) override;
117 };
118 
119 void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate);
120 void FXJS_Release();
121 
122 // Gets the global isolate set by FXJS_Initialize(), or makes a new one each
123 // time if there is no such isolate. Returns true if a new isolate had to be
124 // created.
125 bool FXJS_GetIsolate(v8::Isolate** pResultIsolate);
126 
127 // Get the global isolate's ref count.
128 size_t FXJS_GlobalIsolateRefCount();
129 
130 class CFXJS_Engine {
131  public:
132   explicit CFXJS_Engine(v8::Isolate* pIsolate);
133   ~CFXJS_Engine();
134 
135   using Constructor = void (*)(CFXJS_Engine* pEngine,
136                                v8::Local<v8::Object> obj);
137   using Destructor = void (*)(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj);
138 
139   static CFXJS_Engine* CurrentEngineFromIsolate(v8::Isolate* pIsolate);
140   static int GetObjDefnID(v8::Local<v8::Object> pObj);
141 
GetIsolate()142   v8::Isolate* GetIsolate() const { return m_isolate; }
143 
144   // Always returns a valid, newly-created objDefnID.
145   int DefineObj(const char* sObjName,
146                 FXJSOBJTYPE eObjType,
147                 Constructor pConstructor,
148                 Destructor pDestructor);
149 
150   void DefineObjMethod(int nObjDefnID,
151                        const char* sMethodName,
152                        v8::FunctionCallback pMethodCall);
153   void DefineObjProperty(int nObjDefnID,
154                          const char* sPropName,
155                          v8::AccessorGetterCallback pPropGet,
156                          v8::AccessorSetterCallback pPropPut);
157   void DefineObjAllProperties(int nObjDefnID,
158                               v8::NamedPropertyQueryCallback pPropQurey,
159                               v8::NamedPropertyGetterCallback pPropGet,
160                               v8::NamedPropertySetterCallback pPropPut,
161                               v8::NamedPropertyDeleterCallback pPropDel);
162   void DefineObjConst(int nObjDefnID,
163                       const char* sConstName,
164                       v8::Local<v8::Value> pDefault);
165   void DefineGlobalMethod(const char* sMethodName,
166                           v8::FunctionCallback pMethodCall);
167   void DefineGlobalConst(const wchar_t* sConstName,
168                          v8::FunctionCallback pConstGetter);
169 
170   // Called after FXJS_Define* calls made.
171   void InitializeEngine();
172   void ReleaseEngine();
173 
174   // Called after FXJS_InitializeEngine call made.
175   int Execute(const CFX_WideString& script, FXJSErr* perror);
176 
177   v8::Local<v8::Context> NewLocalContext();
178   v8::Local<v8::Context> GetPersistentContext();
179   v8::Local<v8::Object> GetThisObj();
180 
181   v8::Local<v8::Value> NewNull();
182   v8::Local<v8::Array> NewArray();
183   v8::Local<v8::Value> NewNumber(int number);
184   v8::Local<v8::Value> NewNumber(double number);
185   v8::Local<v8::Value> NewNumber(float number);
186   v8::Local<v8::Value> NewBoolean(bool b);
187   v8::Local<v8::Value> NewString(const CFX_ByteStringC& str);
188   v8::Local<v8::Value> NewString(const CFX_WideStringC& str);
189   v8::Local<v8::Date> NewDate(double d);
190   v8::Local<v8::Object> NewFxDynamicObj(int nObjDefnID, bool bStatic = false);
191 
192   int ToInt32(v8::Local<v8::Value> pValue);
193   bool ToBoolean(v8::Local<v8::Value> pValue);
194   double ToDouble(v8::Local<v8::Value> pValue);
195   CFX_WideString ToWideString(v8::Local<v8::Value> pValue);
196   v8::Local<v8::Object> ToObject(v8::Local<v8::Value> pValue);
197   v8::Local<v8::Array> ToArray(v8::Local<v8::Value> pValue);
198 
199   // Arrays.
200   unsigned GetArrayLength(v8::Local<v8::Array> pArray);
201   v8::Local<v8::Value> GetArrayElement(v8::Local<v8::Array> pArray,
202                                        unsigned index);
203   unsigned PutArrayElement(v8::Local<v8::Array> pArray,
204                            unsigned index,
205                            v8::Local<v8::Value> pValue);
206 
207   // Objects.
208   std::vector<CFX_WideString> GetObjectPropertyNames(
209       v8::Local<v8::Object> pObj);
210   v8::Local<v8::Value> GetObjectProperty(v8::Local<v8::Object> pObj,
211                                          const CFX_WideString& PropertyName);
212   void PutObjectProperty(v8::Local<v8::Object> pObj,
213                          const CFX_WideString& PropertyName,
214                          v8::Local<v8::Value> pValue);
215 
216   // Native object binding.
217   void SetObjectPrivate(v8::Local<v8::Object> pObj, void* p);
218   void* GetObjectPrivate(v8::Local<v8::Object> pObj);
219   static void FreeObjectPrivate(void* p);
220   static void FreeObjectPrivate(v8::Local<v8::Object> pObj);
221 
222   void SetConstArray(const CFX_WideString& name, v8::Local<v8::Array> array);
223   v8::Local<v8::Array> GetConstArray(const CFX_WideString& name);
224 
225   void Error(const CFX_WideString& message);
226 
227  protected:
228   CFXJS_Engine();
229 
SetIsolate(v8::Isolate * pIsolate)230   void SetIsolate(v8::Isolate* pIsolate) { m_isolate = pIsolate; }
231 
232  private:
233   v8::Isolate* m_isolate;
234   v8::Global<v8::Context> m_V8PersistentContext;
235   std::vector<v8::Global<v8::Object>*> m_StaticObjects;
236   std::map<CFX_WideString, v8::Global<v8::Array>> m_ConstArrays;
237 };
238 
239 #endif  // FXJS_FXJS_V8_H_
240