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.
GetWrapper(v8::Isolate * isolate)86   v8::Handle<v8::Object> GetWrapper(v8::Isolate* isolate) {
87     return GetWrapperImpl(isolate, &T::kWrapperInfo);
88   }
89 
90  protected:
Wrappable()91   Wrappable() {}
~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