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