| // Copyright 2015 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef SKY_ENGINE_TONIC_DART_WRAPPABLE_H_ | 
 | #define SKY_ENGINE_TONIC_DART_WRAPPABLE_H_ | 
 |  | 
 | #include "base/logging.h" | 
 | #include "base/template_util.h" | 
 | #include "dart/runtime/include/dart_api.h" | 
 | #include "tonic/dart_converter.h" | 
 | #include "tonic/dart_error.h" | 
 | #include "tonic/dart_state.h" | 
 | #include "tonic/dart_wrapper_info.h" | 
 |  | 
 | namespace blink { | 
 | class DartGCVisitor; | 
 | struct DartWrapperInfo; | 
 |  | 
 | // DartWrappable is a base class that you can inherit from in order to be | 
 | // exposed to Dart code as an interface. | 
 | class DartWrappable { | 
 |  public: | 
 |   enum DartNativeFields { | 
 |     kPeerIndex,  // Must be first to work with Dart_GetNativeReceiver. | 
 |     kWrapperInfoIndex, | 
 |     kNumberOfNativeFields, | 
 |   }; | 
 |  | 
 |   DartWrappable() : dart_wrapper_(nullptr) {} | 
 |  | 
 |   // Subclasses that wish to expose a new interface must override this function | 
 |   // and provide information about their wrapper. There is no need to call your | 
 |   // base class's implementation of this function. | 
 |   virtual const DartWrapperInfo& GetDartWrapperInfo() const = 0; | 
 |  | 
 |   // Subclasses that wish to integrate with the Dart garbage collector should | 
 |   // override this function. Please call your base class's AcceptDartGCVisitor | 
 |   // at the end of your override. | 
 |   virtual void AcceptDartGCVisitor(DartGCVisitor& visitor) const; | 
 |  | 
 |   Dart_Handle CreateDartWrapper(DartState* dart_state); | 
 |   void AssociateWithDartWrapper(Dart_NativeArguments args); | 
 |   Dart_WeakPersistentHandle dart_wrapper() const { return dart_wrapper_; } | 
 |  | 
 |  protected: | 
 |   virtual ~DartWrappable(); | 
 |  | 
 |  private: | 
 |   static void FinalizeDartWrapper(void* isolate_callback_data, | 
 |                                   Dart_WeakPersistentHandle wrapper, | 
 |                                   void* peer); | 
 |  | 
 |   Dart_WeakPersistentHandle dart_wrapper_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(DartWrappable); | 
 | }; | 
 |  | 
 | #define DEFINE_WRAPPERTYPEINFO()                                               \ | 
 |  public:                                                                       \ | 
 |   const DartWrapperInfo& GetDartWrapperInfo() const override {                 \ | 
 |     return dart_wrapper_info_;                                                 \ | 
 |   }                                                                            \ | 
 |  private:                                                                      \ | 
 |   static const DartWrapperInfo& dart_wrapper_info_ | 
 |  | 
 | struct DartConverterWrappable { | 
 |   static DartWrappable* FromDart(Dart_Handle handle); | 
 |   static DartWrappable* FromArguments(Dart_NativeArguments args, | 
 |                                       int index, | 
 |                                       Dart_Handle& exception); | 
 |   static DartWrappable* FromArgumentsWithNullCheck(Dart_NativeArguments args, | 
 |                                                    int index, | 
 |                                                    Dart_Handle& exception); | 
 | }; | 
 |  | 
 | template<typename T> | 
 | struct DartConverter< | 
 |     T*, | 
 |     typename base::enable_if< | 
 |         base::is_convertible<T*, DartWrappable*>::value>::type> { | 
 |   static Dart_Handle ToDart(DartWrappable* val) { | 
 |     if (!val) | 
 |       return Dart_Null(); | 
 |     if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper()) | 
 |       return Dart_HandleFromWeakPersistent(wrapper); | 
 |     return val->CreateDartWrapper(DartState::Current()); | 
 |   } | 
 |  | 
 |   static void SetReturnValue(Dart_NativeArguments args, | 
 |                              DartWrappable* val, | 
 |                              bool auto_scope = true) { | 
 |     if (!val) | 
 |       Dart_SetReturnValue(args, Dart_Null()); | 
 |     else if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper()) | 
 |       Dart_SetWeakHandleReturnValue(args, wrapper); | 
 |     else | 
 |       Dart_SetReturnValue(args, val->CreateDartWrapper(DartState::Current())); | 
 |   } | 
 |  | 
 |   static T* FromDart(Dart_Handle handle) { | 
 |     // TODO(abarth): We're missing a type check. | 
 |     return static_cast<T*>(DartConverterWrappable::FromDart(handle)); | 
 |   } | 
 |  | 
 |   static T* FromArguments(Dart_NativeArguments args, | 
 |                           int index, | 
 |                           Dart_Handle& exception, | 
 |                           bool auto_scope = true) { | 
 |     // TODO(abarth): We're missing a type check. | 
 |     return static_cast<T*>(DartConverterWrappable::FromArguments( | 
 |         args, index, exception)); | 
 |   } | 
 |  | 
 |   static T* FromArgumentsWithNullCheck(Dart_NativeArguments args, | 
 |                                        int index, | 
 |                                        Dart_Handle& exception, | 
 |                                        bool auto_scope = true) { | 
 |     // TODO(abarth): We're missing a type check. | 
 |     return static_cast<T*>(DartConverterWrappable::FromArgumentsWithNullCheck( | 
 |         args, index, exception)); | 
 |   } | 
 | }; | 
 |  | 
 | template<typename T> | 
 | struct DartConverter<RefPtr<T>> { | 
 |   static Dart_Handle ToDart(RefPtr<T> val) { | 
 |     return DartConverter<T*>::ToDart(val.get()); | 
 |   } | 
 |  | 
 |   static RefPtr<T> FromDart(Dart_Handle handle) { | 
 |     return DartConverter<T*>::FromDart(handle); | 
 |   } | 
 | }; | 
 |  | 
 | template<typename T> | 
 | inline T* GetReceiver(Dart_NativeArguments args) { | 
 |   intptr_t receiver; | 
 |   Dart_Handle result = Dart_GetNativeReceiver(args, &receiver); | 
 |   DCHECK(!Dart_IsError(result)); | 
 |   return static_cast<T*>(reinterpret_cast<DartWrappable*>(receiver)); | 
 | } | 
 |  | 
 | }  // namespace blink | 
 |  | 
 | #endif  // SKY_ENGINE_TONIC_DART_WRAPPABLE_H_ |