OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef GIN_WRAPPABLE_H_ | 5 #ifndef GIN_WRAPPABLE_H_ |
6 #define GIN_WRAPPABLE_H_ | 6 #define GIN_WRAPPABLE_H_ |
7 | 7 |
8 #include "base/template_util.h" | |
8 #include "gin/converter.h" | 9 #include "gin/converter.h" |
9 #include "gin/public/wrapper_info.h" | 10 #include "gin/public/wrapper_info.h" |
10 | 11 |
11 namespace gin { | 12 namespace gin { |
12 | 13 |
13 // Wrappable is an abstract base class for C++ objects that have cooresponding | 14 // Wrappable is an abstract base class for C++ objects that have cooresponding |
14 // v8 wrapper objects. To retain a Wrappable object on the stack, use a | 15 // v8 wrapper objects. To retain a Wrappable object on the stack, use a |
15 // gin::Handle. | 16 // gin::Handle. |
16 class Wrappable { | 17 class Wrappable { |
17 public: | 18 public: |
(...skipping 28 matching lines...) Expand all Loading... | |
46 // Create function will enforce that clients actually create a wrapper for | 47 // Create function will enforce that clients actually create a wrapper for |
47 // the object. If clients fail to create a wrapper for a wrappable object, | 48 // the object. If clients fail to create a wrapper for a wrappable object, |
48 // the object will leak because we use the weak callback from the wrapper | 49 // the object will leak because we use the weak callback from the wrapper |
49 // as the signal to delete the wrapped object. | 50 // as the signal to delete the wrapped object. |
50 | 51 |
51 protected: | 52 protected: |
52 Wrappable(); | 53 Wrappable(); |
53 virtual ~Wrappable(); | 54 virtual ~Wrappable(); |
54 | 55 |
55 private: | 56 private: |
56 friend struct Converter<Wrappable*>; | |
57 | |
58 static void WeakCallback( | 57 static void WeakCallback( |
59 const v8::WeakCallbackData<v8::Object, Wrappable>& data); | 58 const v8::WeakCallbackData<v8::Object, Wrappable>& data); |
60 v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate); | 59 v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate); |
61 | 60 |
62 v8::Persistent<v8::Object> wrapper_; // Weak | 61 v8::Persistent<v8::Object> wrapper_; // Weak |
63 | 62 |
64 DISALLOW_COPY_AND_ASSIGN(Wrappable); | 63 DISALLOW_COPY_AND_ASSIGN(Wrappable); |
65 }; | 64 }; |
66 | 65 |
67 template<> | 66 // This converter handles any subclass of Wrappable. |
68 struct Converter<Wrappable*> { | 67 template<typename T> |
69 static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, | 68 struct Converter<T, typename base::enable_if< |
70 Wrappable* val); | 69 base::is_convertible<T, Wrappable*>::value>::type> { |
71 static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, | 70 static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T val) { |
72 Wrappable** out); | 71 return val->GetWrapper(isolate); |
73 }; | 72 } |
74 | 73 |
75 template<typename T> | 74 static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T* out) { |
76 struct WrappableConverter { | 75 if (!val->IsObject()) |
77 static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) { | |
78 return Converter<Wrappable*>::ToV8(isolate, val); | |
79 } | |
80 static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) { | |
81 Wrappable* wrappable = NULL; | |
82 if (!Converter<Wrappable*>::FromV8(isolate, val, &wrappable) | |
83 || wrappable->GetWrapperInfo() != &T::kWrapperInfo) | |
abarth-chromium
2013/12/06 01:50:55
I think we're missing this security check. You ne
| |
84 return false; | 76 return false; |
85 // Currently we require that you unwrap to the exact runtime type of the | 77 v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(val); |
86 // wrapped object. | 78 WrapperInfo* info = WrapperInfo::From(obj); |
87 // TODO(abarth): Support unwrapping to a base class. | 79 if (!info) |
88 *out = static_cast<T*>(wrappable); | 80 return false; |
81 void* pointer = obj->GetAlignedPointerFromInternalField(kEncodedValueIndex); | |
82 T result = static_cast<T>(pointer); | |
83 CHECK(result->GetWrapperInfo() == info); // Security check for cast above. | |
84 *out = result; | |
89 return true; | 85 return true; |
90 } | 86 } |
91 }; | 87 }; |
92 | 88 |
93 } // namespace gin | 89 } // namespace gin |
94 | 90 |
95 #endif // GIN_WRAPPABLE_H_ | 91 #endif // GIN_WRAPPABLE_H_ |
OLD | NEW |