Home | History | Annotate | Download | only in gin
      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.
     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.
    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