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 //   ...
     31 // };
     32 //
     33 // // my_class.cc
     34 // INIT_WRAPABLE(MyClass);
     35 //
     36 // Subclasses should also typically have private constructors and expose a
     37 // static Create function that returns a gin::Handle. Forcing creators through
     38 // this static Create function will enforce that clients actually create a
     39 // wrapper for the object. If clients fail to create a wrapper for a wrappable
     40 // object, the object will leak because we use the weak callback from the
     41 // wrapper as the signal to delete the wrapped object.
     42 template<typename T>
     43 class Wrappable;
     44 
     45 
     46 // Non-template base class to share code between templates instances.
     47 class GIN_EXPORT WrappableBase {
     48  protected:
     49   WrappableBase();
     50   virtual ~WrappableBase();
     51   v8::Handle<v8::Object> GetWrapperImpl(v8::Isolate* isolate,
     52                                         WrapperInfo* wrapper_info);
     53   v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate,
     54                                        WrapperInfo* wrapper_info);
     55   v8::Persistent<v8::Object> wrapper_;  // Weak
     56 
     57  private:
     58   static void WeakCallback(
     59       const v8::WeakCallbackData<v8::Object, WrappableBase>& data);
     60 
     61   DISALLOW_COPY_AND_ASSIGN(WrappableBase);
     62 };
     63 
     64 
     65 template<typename T>
     66 class Wrappable : public WrappableBase {
     67  public:
     68   // Retrieve (or create) the v8 wrapper object cooresponding to this object.
     69   // To customize the wrapper created for a subclass, override GetWrapperInfo()
     70   // instead of overriding this function.
     71   v8::Handle<v8::Object> GetWrapper(v8::Isolate* isolate) {
     72     return GetWrapperImpl(isolate, &T::kWrapperInfo);
     73   }
     74 
     75  protected:
     76   Wrappable() {}
     77   virtual ~Wrappable() {}
     78 
     79  private:
     80   DISALLOW_COPY_AND_ASSIGN(Wrappable);
     81 };
     82 
     83 
     84 // This converter handles any subclass of Wrappable.
     85 template<typename T>
     86 struct Converter<T*, typename base::enable_if<
     87                        base::is_convertible<T*, Wrappable<T>*>::value>::type> {
     88   static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) {
     89     return val->GetWrapper(isolate);
     90   }
     91 
     92   static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) {
     93     *out = static_cast<T*>(internal::FromV8Impl(isolate, val,
     94                                                 &T::kWrapperInfo));
     95     return *out != NULL;
     96   }
     97 };
     98 
     99 }  // namespace gin
    100 
    101 #endif  // GIN_WRAPPABLE_H_
    102