| // Copyright 2013 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 GIN_OBJECT_TEMPLATE_BUILDER_H_ | 
 | #define GIN_OBJECT_TEMPLATE_BUILDER_H_ | 
 |  | 
 | #include "base/bind.h" | 
 | #include "base/callback.h" | 
 | #include "base/strings/string_piece.h" | 
 | #include "base/template_util.h" | 
 | #include "gin/converter.h" | 
 | #include "gin/function_template.h" | 
 | #include "gin/gin_export.h" | 
 | #include "v8/include/v8.h" | 
 |  | 
 | namespace gin { | 
 |  | 
 | namespace { | 
 |  | 
 | // Base template - used only for non-member function pointers. Other types | 
 | // either go to one of the below specializations, or go here and fail to compile | 
 | // because of base::Bind(). | 
 | template<typename T, typename Enable = void> | 
 | struct CallbackTraits { | 
 |   static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate, | 
 |                                                          T callback) { | 
 |     return CreateFunctionTemplate(isolate, base::Bind(callback)); | 
 |   } | 
 |   static void SetAsFunctionHandler(v8::Isolate* isolate, | 
 |                                    v8::Local<v8::ObjectTemplate> tmpl, | 
 |                                    T callback) { | 
 |     CreateFunctionHandler(isolate, tmpl, base::Bind(callback)); | 
 |   } | 
 | }; | 
 |  | 
 | // Specialization for base::Callback. | 
 | template<typename T> | 
 | struct CallbackTraits<base::Callback<T> > { | 
 |   static v8::Handle<v8::FunctionTemplate> CreateTemplate( | 
 |       v8::Isolate* isolate, const base::Callback<T>& callback) { | 
 |     return CreateFunctionTemplate(isolate, callback); | 
 |   } | 
 |   static void SetAsFunctionHandler(v8::Isolate* isolate, | 
 |                                    v8::Local<v8::ObjectTemplate> tmpl, | 
 |                                    const base::Callback<T>& callback) { | 
 |     CreateFunctionHandler(isolate, tmpl, callback); | 
 |   } | 
 | }; | 
 |  | 
 | // Specialization for member function pointers. We need to handle this case | 
 | // specially because the first parameter for callbacks to MFP should typically | 
 | // come from the the JavaScript "this" object the function was called on, not | 
 | // from the first normal parameter. | 
 | template<typename T> | 
 | struct CallbackTraits<T, typename base::enable_if< | 
 |                            base::is_member_function_pointer<T>::value>::type> { | 
 |   static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate, | 
 |                                                          T callback) { | 
 |     return CreateFunctionTemplate(isolate, base::Bind(callback), | 
 |                                   HolderIsFirstArgument); | 
 |   } | 
 |   static void SetAsFunctionHandler(v8::Isolate* isolate, | 
 |                                    v8::Local<v8::ObjectTemplate> tmpl, | 
 |                                    T callback) { | 
 |     CreateFunctionHandler( | 
 |         isolate, tmpl, base::Bind(callback), HolderIsFirstArgument); | 
 |   } | 
 | }; | 
 |  | 
 | // This specialization allows people to construct function templates directly if | 
 | // they need to do fancier stuff. | 
 | template<> | 
 | struct CallbackTraits<v8::Handle<v8::FunctionTemplate> > { | 
 |   static v8::Handle<v8::FunctionTemplate> CreateTemplate( | 
 |       v8::Handle<v8::FunctionTemplate> templ) { | 
 |     return templ; | 
 |   } | 
 | }; | 
 |  | 
 | }  // namespace | 
 |  | 
 |  | 
 | // ObjectTemplateBuilder provides a handy interface to creating | 
 | // v8::ObjectTemplate instances with various sorts of properties. | 
 | class GIN_EXPORT ObjectTemplateBuilder { | 
 |  public: | 
 |   explicit ObjectTemplateBuilder(v8::Isolate* isolate); | 
 |   ~ObjectTemplateBuilder(); | 
 |  | 
 |   // It's against Google C++ style to return a non-const ref, but we take some | 
 |   // poetic license here in order that all calls to Set() can be via the '.' | 
 |   // operator and line up nicely. | 
 |   template<typename T> | 
 |   ObjectTemplateBuilder& SetValue(const base::StringPiece& name, T val) { | 
 |     return SetImpl(name, ConvertToV8(isolate_, val)); | 
 |   } | 
 |  | 
 |   // In the following methods, T and U can be function pointer, member function | 
 |   // pointer, base::Callback, or v8::FunctionTemplate. Most clients will want to | 
 |   // use one of the first two options. Also see gin::CreateFunctionTemplate() | 
 |   // for creating raw function templates. | 
 |   template<typename T> | 
 |   ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, | 
 |                                    const T& callback) { | 
 |     return SetImpl(name, CallbackTraits<T>::CreateTemplate(isolate_, callback)); | 
 |   } | 
 |   template<typename T> | 
 |   ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, | 
 |                                      const T& getter) { | 
 |     return SetPropertyImpl(name, | 
 |                            CallbackTraits<T>::CreateTemplate(isolate_, getter), | 
 |                            v8::Local<v8::FunctionTemplate>()); | 
 |   } | 
 |   template<typename T, typename U> | 
 |   ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, | 
 |                                      const T& getter, const U& setter) { | 
 |     return SetPropertyImpl(name, | 
 |                            CallbackTraits<T>::CreateTemplate(isolate_, getter), | 
 |                            CallbackTraits<U>::CreateTemplate(isolate_, setter)); | 
 |   } | 
 |   template<typename T> | 
 |   ObjectTemplateBuilder& SetCallAsFunctionHandler(const T& callback) { | 
 |     CallbackTraits<T>::SetAsFunctionHandler(isolate_, template_, callback); | 
 |     return *this; | 
 |   } | 
 |   ObjectTemplateBuilder& AddNamedPropertyInterceptor(); | 
 |   ObjectTemplateBuilder& AddIndexedPropertyInterceptor(); | 
 |  | 
 |   v8::Local<v8::ObjectTemplate> Build(); | 
 |  | 
 |  private: | 
 |   ObjectTemplateBuilder& SetImpl(const base::StringPiece& name, | 
 |                                  v8::Handle<v8::Data> val); | 
 |   ObjectTemplateBuilder& SetPropertyImpl( | 
 |       const base::StringPiece& name, v8::Handle<v8::FunctionTemplate> getter, | 
 |       v8::Handle<v8::FunctionTemplate> setter); | 
 |  | 
 |   v8::Isolate* isolate_; | 
 |  | 
 |   // ObjectTemplateBuilder should only be used on the stack. | 
 |   v8::Local<v8::ObjectTemplate> template_; | 
 | }; | 
 |  | 
 | }  // namespace gin | 
 |  | 
 | #endif  // GIN_OBJECT_TEMPLATE_BUILDER_H_ |