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