• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The PDFium Authors
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 // CFXJS_ENGINE is a layer that makes it easier to define native objects in V8,
8 // but has no knowledge of PDF-specific native objects. It could in theory be
9 // used 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_CFXJS_ENGINE_H_
15 #define FXJS_CFXJS_ENGINE_H_
16 
17 #include <functional>
18 #include <map>
19 #include <memory>
20 #include <utility>
21 #include <vector>
22 
23 #include "core/fxcrt/widestring.h"
24 #include "fxjs/cfx_v8.h"
25 #include "fxjs/ijs_runtime.h"
26 #include "v8/include/v8-forward.h"
27 #include "v8/include/v8-function-callback.h"
28 #include "v8/include/v8-persistent-handle.h"
29 #include "v8/include/v8-template.h"
30 
31 class CFXJS_ObjDefinition;
32 class V8TemplateMap;
33 
34 enum FXJSOBJTYPE {
35   FXJSOBJTYPE_DYNAMIC = 0,  // Created by native method and returned to JS.
36   FXJSOBJTYPE_STATIC,       // Created by init and hung off of global object.
37   FXJSOBJTYPE_GLOBAL,       // The global object itself (may only appear once).
38 };
39 
40 class CFXJS_PerIsolateData {
41  public:
42   // Hook for XFA's data, when present.
43   class ExtensionIface {
44    public:
45     virtual ~ExtensionIface() = default;
46   };
47 
48   ~CFXJS_PerIsolateData();
49 
50   static void SetUp(v8::Isolate* pIsolate);
51   static CFXJS_PerIsolateData* Get(v8::Isolate* pIsolate);
52 
53   uint32_t CurrentMaxObjDefinitionID() const;
54   CFXJS_ObjDefinition* ObjDefinitionForID(uint32_t id) const;
55   uint32_t AssignIDForObjDefinition(std::unique_ptr<CFXJS_ObjDefinition> pDefn);
GetDynamicObjsMap()56   V8TemplateMap* GetDynamicObjsMap() { return m_pDynamicObjsMap.get(); }
GetExtension()57   ExtensionIface* GetExtension() { return m_pExtension.get(); }
SetExtension(std::unique_ptr<ExtensionIface> extension)58   void SetExtension(std::unique_ptr<ExtensionIface> extension) {
59     m_pExtension = std::move(extension);
60   }
61 
62  private:
63   explicit CFXJS_PerIsolateData(v8::Isolate* pIsolate);
64 
65   const wchar_t* const m_Tag;  // Raw, always a literal.
66   std::vector<std::unique_ptr<CFXJS_ObjDefinition>> m_ObjectDefnArray;
67   std::unique_ptr<V8TemplateMap> m_pDynamicObjsMap;
68   std::unique_ptr<ExtensionIface> m_pExtension;
69 };
70 
71 class CFXJS_PerObjectData {
72  public:
73   // Object on the C++ side to which the v8::Object is bound.
74   class Binding {
75    public:
76     virtual ~Binding() = default;
77   };
78 
79   static void SetNewDataInObject(FXJSOBJTYPE eObjType,
80                                  uint32_t nObjDefnID,
81                                  v8::Local<v8::Object> pObj);
82   static CFXJS_PerObjectData* GetFromObject(v8::Local<v8::Object> pObj);
83 
84   ~CFXJS_PerObjectData();
85 
GetObjDefnID()86   uint32_t GetObjDefnID() const { return m_ObjDefnID; }
GetBinding()87   Binding* GetBinding() { return m_pBinding.get(); }
SetBinding(std::unique_ptr<Binding> p)88   void SetBinding(std::unique_ptr<Binding> p) { m_pBinding = std::move(p); }
89 
90  private:
91   CFXJS_PerObjectData(FXJSOBJTYPE eObjType, uint32_t nObjDefnID);
92 
93   static bool HasInternalFields(v8::Local<v8::Object> pObj);
94   static CFXJS_PerObjectData* ExtractFromObject(v8::Local<v8::Object> pObj);
95 
96   const FXJSOBJTYPE m_ObjType;
97   const uint32_t m_ObjDefnID;
98   std::unique_ptr<Binding> m_pBinding;
99 };
100 
101 void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate);
102 void FXJS_Release();
103 
104 // Gets the global isolate set by FXJS_Initialize(), or makes a new one each
105 // time if there is no such isolate. Returns true if a new isolate had to be
106 // created.
107 bool FXJS_GetIsolate(v8::Isolate** pResultIsolate);
108 
109 // Get the global isolate's ref count.
110 size_t FXJS_GlobalIsolateRefCount();
111 
112 class CFXJS_Engine : public CFX_V8 {
113  public:
114   explicit CFXJS_Engine(v8::Isolate* pIsolate);
115   ~CFXJS_Engine() override;
116 
117   using Constructor = std::function<void(CFXJS_Engine* pEngine,
118                                          v8::Local<v8::Object> obj,
119                                          v8::Local<v8::Object> proxy)>;
120   using Destructor = std::function<void(v8::Local<v8::Object> obj)>;
121 
122   static uint32_t GetObjDefnID(v8::Local<v8::Object> pObj);
123   static CFXJS_PerObjectData::Binding* GetBinding(v8::Isolate* pIsolate,
124                                                   v8::Local<v8::Object> pObj);
125   static void SetBinding(v8::Local<v8::Object> pObj,
126                          std::unique_ptr<CFXJS_PerObjectData::Binding> p);
127   static void FreePerObjectData(v8::Local<v8::Object> pObj);
128 
129   // Always returns a valid (i.e. non-zero), newly-created objDefnID.
130   uint32_t DefineObj(const char* sObjName,
131                      FXJSOBJTYPE eObjType,
132                      Constructor pConstructor,
133                      Destructor pDestructor);
134 
135   void DefineObjMethod(uint32_t nObjDefnID,
136                        const char* sMethodName,
137                        v8::FunctionCallback pMethodCall);
138   void DefineObjProperty(uint32_t nObjDefnID,
139                          const char* sPropName,
140                          v8::AccessorNameGetterCallback pPropGet,
141                          v8::AccessorNameSetterCallback pPropPut);
142   void DefineObjAllProperties(uint32_t nObjDefnID,
143                               v8::NamedPropertyQueryCallback pPropQurey,
144                               v8::NamedPropertyGetterCallback pPropGet,
145                               v8::NamedPropertySetterCallback pPropPut,
146                               v8::NamedPropertyDeleterCallback pPropDel,
147                               v8::NamedPropertyEnumeratorCallback pPropEnum);
148   void DefineObjConst(uint32_t nObjDefnID,
149                       const char* sConstName,
150                       v8::Local<v8::Value> pDefault);
151   void DefineGlobalMethod(const char* sMethodName,
152                           v8::FunctionCallback pMethodCall);
153   void DefineGlobalConst(const wchar_t* sConstName,
154                          v8::FunctionCallback pConstGetter);
155 
156   // Called after FXJS_Define* calls made.
157   void InitializeEngine();
158   void ReleaseEngine();
159 
160   // Called after FXJS_InitializeEngine call made.
161   std::optional<IJS_Runtime::JS_Error> Execute(const WideString& script);
162 
163   v8::Local<v8::Object> GetThisObj();
164   v8::Local<v8::Object> NewFXJSBoundObject(uint32_t nObjDefnID,
165                                            FXJSOBJTYPE type);
166   void Error(const WideString& message);
167 
168   v8::Local<v8::Context> GetV8Context();
169 
170   v8::Local<v8::Array> GetConstArray(const WideString& name);
171   void SetConstArray(const WideString& name, v8::Local<v8::Array> array);
172 
173  protected:
174   CFXJS_Engine();
175 
176  private:
177   v8::Global<v8::Context> m_V8Context;
178   std::vector<v8::Global<v8::Object>> m_StaticObjects;
179   std::map<WideString, v8::Global<v8::Array>> m_ConstArrays;
180 };
181 
182 #endif  // FXJS_CFXJS_ENGINE_H_
183