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 // ... 31 // }; 32 // 33 // // my_class.cc 34 // INIT_WRAPABLE(MyClass); 35 // 36 // Subclasses should also typically have private constructors and expose a 37 // static Create function that returns a gin::Handle. Forcing creators through 38 // this static Create function will enforce that clients actually create a 39 // wrapper for the object. If clients fail to create a wrapper for a wrappable 40 // object, the object will leak because we use the weak callback from the 41 // wrapper as the signal to delete the wrapped object. 42 template<typename T> 43 class Wrappable; 44 45 46 // Non-template base class to share code between templates instances. 47 class GIN_EXPORT WrappableBase { 48 protected: 49 WrappableBase(); 50 virtual ~WrappableBase(); 51 v8::Handle<v8::Object> GetWrapperImpl(v8::Isolate* isolate, 52 WrapperInfo* wrapper_info); 53 v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate, 54 WrapperInfo* wrapper_info); 55 v8::Persistent<v8::Object> wrapper_; // Weak 56 57 private: 58 static void WeakCallback( 59 const v8::WeakCallbackData<v8::Object, WrappableBase>& data); 60 61 DISALLOW_COPY_AND_ASSIGN(WrappableBase); 62 }; 63 64 65 template<typename T> 66 class Wrappable : public WrappableBase { 67 public: 68 // Retrieve (or create) the v8 wrapper object cooresponding to this object. 69 // To customize the wrapper created for a subclass, override GetWrapperInfo() 70 // instead of overriding this function. 71 v8::Handle<v8::Object> GetWrapper(v8::Isolate* isolate) { 72 return GetWrapperImpl(isolate, &T::kWrapperInfo); 73 } 74 75 protected: 76 Wrappable() {} 77 virtual ~Wrappable() {} 78 79 private: 80 DISALLOW_COPY_AND_ASSIGN(Wrappable); 81 }; 82 83 84 // This converter handles any subclass of Wrappable. 85 template<typename T> 86 struct Converter<T*, typename base::enable_if< 87 base::is_convertible<T*, Wrappable<T>*>::value>::type> { 88 static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) { 89 return val->GetWrapper(isolate); 90 } 91 92 static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) { 93 *out = static_cast<T*>(internal::FromV8Impl(isolate, val, 94 &T::kWrapperInfo)); 95 return *out != NULL; 96 } 97 }; 98 99 } // namespace gin 100 101 #endif // GIN_WRAPPABLE_H_ 102