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 CJS_Object; 33 class V8TemplateMap; 34 35 enum FXJSOBJTYPE { 36 FXJSOBJTYPE_DYNAMIC = 0, // Created by native method and returned to JS. 37 FXJSOBJTYPE_STATIC, // Created by init and hung off of global object. 38 FXJSOBJTYPE_GLOBAL, // The global object itself (may only appear once). 39 }; 40 41 class FXJS_PerIsolateData { 42 public: 43 // Hook for XFA's data, when present. 44 class ExtensionIface { 45 public: 46 virtual ~ExtensionIface() = default; 47 }; 48 49 ~FXJS_PerIsolateData(); 50 51 static void SetUp(v8::Isolate* pIsolate); 52 static FXJS_PerIsolateData* Get(v8::Isolate* pIsolate); 53 54 uint32_t CurrentMaxObjDefinitionID() const; 55 CFXJS_ObjDefinition* ObjDefinitionForID(uint32_t id) const; 56 uint32_t AssignIDForObjDefinition(std::unique_ptr<CFXJS_ObjDefinition> pDefn); GetDynamicObjsMap()57 V8TemplateMap* GetDynamicObjsMap() { return m_pDynamicObjsMap.get(); } GetExtension()58 ExtensionIface* GetExtension() { return m_pExtension.get(); } SetExtension(std::unique_ptr<ExtensionIface> extension)59 void SetExtension(std::unique_ptr<ExtensionIface> extension) { 60 m_pExtension = std::move(extension); 61 } 62 63 private: 64 explicit FXJS_PerIsolateData(v8::Isolate* pIsolate); 65 66 const wchar_t* const m_Tag; // Raw, always a literal. 67 std::vector<std::unique_ptr<CFXJS_ObjDefinition>> m_ObjectDefnArray; 68 std::unique_ptr<V8TemplateMap> m_pDynamicObjsMap; 69 std::unique_ptr<ExtensionIface> m_pExtension; 70 }; 71 72 void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate); 73 void FXJS_Release(); 74 75 // Gets the global isolate set by FXJS_Initialize(), or makes a new one each 76 // time if there is no such isolate. Returns true if a new isolate had to be 77 // created. 78 bool FXJS_GetIsolate(v8::Isolate** pResultIsolate); 79 80 // Get the global isolate's ref count. 81 size_t FXJS_GlobalIsolateRefCount(); 82 83 class CFXJS_Engine : public CFX_V8 { 84 public: 85 explicit CFXJS_Engine(v8::Isolate* pIsolate); 86 ~CFXJS_Engine() override; 87 88 using Constructor = std::function<void(CFXJS_Engine* pEngine, 89 v8::Local<v8::Object> obj, 90 v8::Local<v8::Object> proxy)>; 91 using Destructor = std::function<void(v8::Local<v8::Object> obj)>; 92 93 static uint32_t GetObjDefnID(v8::Local<v8::Object> pObj); 94 static CJS_Object* GetObjectPrivate(v8::Isolate* pIsolate, 95 v8::Local<v8::Object> pObj); 96 static void SetObjectPrivate(v8::Local<v8::Object> pObj, 97 std::unique_ptr<CJS_Object> p); 98 static void FreeObjectPrivate(v8::Local<v8::Object> pObj); 99 100 // Always returns a valid (i.e. non-zero), newly-created objDefnID. 101 uint32_t DefineObj(const char* sObjName, 102 FXJSOBJTYPE eObjType, 103 Constructor pConstructor, 104 Destructor pDestructor); 105 106 void DefineObjMethod(uint32_t nObjDefnID, 107 const char* sMethodName, 108 v8::FunctionCallback pMethodCall); 109 void DefineObjProperty(uint32_t nObjDefnID, 110 const char* sPropName, 111 v8::AccessorGetterCallback pPropGet, 112 v8::AccessorSetterCallback pPropPut); 113 void DefineObjAllProperties( 114 uint32_t nObjDefnID, 115 v8::GenericNamedPropertyQueryCallback pPropQurey, 116 v8::GenericNamedPropertyGetterCallback pPropGet, 117 v8::GenericNamedPropertySetterCallback pPropPut, 118 v8::GenericNamedPropertyDeleterCallback pPropDel, 119 v8::GenericNamedPropertyEnumeratorCallback pPropEnum); 120 void DefineObjConst(uint32_t nObjDefnID, 121 const char* sConstName, 122 v8::Local<v8::Value> pDefault); 123 void DefineGlobalMethod(const char* sMethodName, 124 v8::FunctionCallback pMethodCall); 125 void DefineGlobalConst(const wchar_t* sConstName, 126 v8::FunctionCallback pConstGetter); 127 128 // Called after FXJS_Define* calls made. 129 void InitializeEngine(); 130 void ReleaseEngine(); 131 132 // Called after FXJS_InitializeEngine call made. 133 absl::optional<IJS_Runtime::JS_Error> Execute(const WideString& script); 134 135 v8::Local<v8::Object> GetThisObj(); 136 v8::Local<v8::Object> NewFXJSBoundObject(uint32_t nObjDefnID, 137 FXJSOBJTYPE type); 138 void Error(const WideString& message); 139 140 v8::Local<v8::Context> GetV8Context(); 141 142 v8::Local<v8::Array> GetConstArray(const WideString& name); 143 void SetConstArray(const WideString& name, v8::Local<v8::Array> array); 144 145 protected: 146 CFXJS_Engine(); 147 148 private: 149 v8::Global<v8::Context> m_V8Context; 150 std::vector<v8::Global<v8::Object>> m_StaticObjects; 151 std::map<WideString, v8::Global<v8::Array>> m_ConstArrays; 152 }; 153 154 #endif // FXJS_CFXJS_ENGINE_H_ 155