1 // Copyright 2013 The Chromium 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 #ifndef GIN_WRAPPABLE_H_ 6 #define GIN_WRAPPABLE_H_ 7 8 #include "base/template_util.h" 9 #include "gin/converter.h" 10 #include "gin/gin_export.h" 11 #include "gin/public/wrapper_info.h" 12 13 namespace gin { 14 15 namespace internal { 16 17 GIN_EXPORT void* FromV8Impl(v8::Isolate* isolate, 18 v8::Handle<v8::Value> val, 19 WrapperInfo* info); 20 21 } // namespace internal 22 23 24 // Wrappable is a base class for C++ objects that have corresponding v8 wrapper 25 // objects. To retain a Wrappable object on the stack, use a gin::Handle. 26 // 27 // USAGE: 28 // // my_class.h 29 // class MyClass : Wrappable<MyClass> { 30 // public: 31 // static WrapperInfo kWrapperInfo; 32 // 33 // // Optional, only required if non-empty template should be used. 34 // virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder( 35 // v8::Isolate* isolate); 36 // ... 37 // }; 38 // 39 // // my_class.cc 40 // WrapperInfo MyClass::kWrapperInfo = {kEmbedderNativeGin}; 41 // 42 // gin::ObjectTemplateBuilder MyClass::GetObjectTemplateBuilder( 43 // v8::Isolate* isolate) { 44 // return Wrappable<MyClass>::GetObjectTemplateBuilder(isolate) 45 // .SetValue("foobar", 42); 46 // } 47 // 48 // Subclasses should also typically have private constructors and expose a 49 // static Create function that returns a gin::Handle. Forcing creators through 50 // this static Create function will enforce that clients actually create a 51 // wrapper for the object. If clients fail to create a wrapper for a wrappable 52 // object, the object will leak because we use the weak callback from the 53 // wrapper as the signal to delete the wrapped object. 54 template<typename T> 55 class Wrappable; 56 57 class ObjectTemplateBuilder; 58 59 // Non-template base class to share code between templates instances. 60 class GIN_EXPORT WrappableBase { 61 protected: 62 WrappableBase(); 63 virtual ~WrappableBase(); 64 65 virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate); 66 67 v8::Handle<v8::Object> GetWrapperImpl(v8::Isolate* isolate, 68 WrapperInfo* wrapper_info); 69 70 private: 71 static void WeakCallback( 72 const v8::WeakCallbackData<v8::Object, WrappableBase>& data); 73 74 v8::Persistent<v8::Object> wrapper_; // Weak 75 76 DISALLOW_COPY_AND_ASSIGN(WrappableBase); 77 }; 78 79 80 template<typename T> 81 class Wrappable : public WrappableBase { 82 public: 83 // Retrieve (or create) the v8 wrapper object cooresponding to this object. 84 // To customize the wrapper created for a subclass, override GetWrapperInfo() 85 // instead of overriding this function. 86 v8::Handle<v8::Object> GetWrapper(v8::Isolate* isolate) { 87 return GetWrapperImpl(isolate, &T::kWrapperInfo); 88 } 89 90 protected: 91 Wrappable() {} 92 virtual ~Wrappable() {} 93 94 private: 95 DISALLOW_COPY_AND_ASSIGN(Wrappable); 96 }; 97 98 99 // This converter handles any subclass of Wrappable. 100 template<typename T> 101 struct Converter<T*, typename base::enable_if< 102 base::is_convertible<T*, WrappableBase*>::value>::type> { 103 static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) { 104 return val->GetWrapper(isolate); 105 } 106 107 static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) { 108 *out = static_cast<T*>(static_cast<WrappableBase*>( 109 internal::FromV8Impl(isolate, val, &T::kWrapperInfo))); 110 return *out != NULL; 111 } 112 }; 113 114 } // namespace gin 115 116 #endif // GIN_WRAPPABLE_H_ 117