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 13namespace gin { 14 15namespace internal { 16 17GIN_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. 54template<typename T> 55class Wrappable; 56 57class ObjectTemplateBuilder; 58 59// Non-template base class to share code between templates instances. 60class 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 80template<typename T> 81class 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. 100template<typename T> 101struct 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