blob: ff52b19a06f57c2d930efbfa149a8f03897f9fe3 [file] [log] [blame]
James Robinsona9763132014-10-06 11:18:13 -07001// 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_