Skip to content

Commit

Permalink
Add support for wrapping classes indirectly inherited from gin::Wrapp…
Browse files Browse the repository at this point in the history
…able<T>

This is needed for: https://codereview.chromium.org/116163008/

Review URL: https://codereview.chromium.org/118423004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@241730 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
aa@chromium.org committed Dec 19, 2013
1 parent 40e1676 commit 13c977e
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 63 deletions.
21 changes: 10 additions & 11 deletions content/renderer/stats_collection_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,6 @@ gin::WrapperInfo StatsCollectionController::kWrapperInfo = {
gin::kEmbedderNativeGin
};

// static
v8::Local<v8::ObjectTemplate> StatsCollectionController::GetObjectTemplate(
v8::Isolate* isolate) {
return gin::ObjectTemplateBuilder(isolate)
.SetMethod("getHistogram", &StatsCollectionController::GetHistogram)
.SetMethod("getBrowserHistogram",
&StatsCollectionController::GetBrowserHistogram)
.SetMethod("tabLoadTiming", &StatsCollectionController::GetTabLoadTiming)
.Build();
}

// static
void StatsCollectionController::Install(blink::WebFrame* frame) {
v8::Isolate* isolate = blink::mainThreadIsolate();
Expand All @@ -106,6 +95,16 @@ StatsCollectionController::StatsCollectionController() {}

StatsCollectionController::~StatsCollectionController() {}

gin::ObjectTemplateBuilder StatsCollectionController::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return gin::Wrappable<StatsCollectionController>::GetObjectTemplateBuilder(
isolate)
.SetMethod("getHistogram", &StatsCollectionController::GetHistogram)
.SetMethod("getBrowserHistogram",
&StatsCollectionController::GetBrowserHistogram)
.SetMethod("tabLoadTiming", &StatsCollectionController::GetTabLoadTiming);
}

std::string StatsCollectionController::GetHistogram(
const std::string& histogram_name) {
base::HistogramBase* histogram =
Expand Down
5 changes: 4 additions & 1 deletion content/renderer/stats_collection_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,17 @@ class StatsCollectionController
: public gin::Wrappable<StatsCollectionController> {
public:
static gin::WrapperInfo kWrapperInfo;
static v8::Local<v8::ObjectTemplate> GetObjectTemplate(v8::Isolate* isolate);

static void Install(blink::WebFrame* frame);

private:
StatsCollectionController();
virtual ~StatsCollectionController();

// gin::WrappableBase
virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) OVERRIDE;

// Retrieves a histogram and returns a JSON representation of it.
std::string GetHistogram(const std::string& histogram_name);

Expand Down
25 changes: 9 additions & 16 deletions gin/wrappable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,9 @@ WrappableBase::~WrappableBase() {
wrapper_.Reset();
}

v8::Handle<v8::Object> WrappableBase::GetWrapperImpl(
v8::Isolate* isolate,
WrapperInfo* wrapper_info,
GetObjectTemplateFunction template_getter) {
if (wrapper_.IsEmpty())
CreateWrapper(isolate, wrapper_info, template_getter);
return v8::Local<v8::Object>::New(isolate, wrapper_);
}

v8::Local<v8::ObjectTemplate> WrappableBase::GetObjectTemplate(
ObjectTemplateBuilder WrappableBase::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return ObjectTemplateBuilder(isolate).Build();
return ObjectTemplateBuilder(isolate);
}

void WrappableBase::WeakCallback(
Expand All @@ -38,14 +29,16 @@ void WrappableBase::WeakCallback(
delete wrappable;
}

v8::Handle<v8::Object> WrappableBase::CreateWrapper(
v8::Isolate* isolate,
WrapperInfo* info,
GetObjectTemplateFunction template_getter) {
v8::Handle<v8::Object> WrappableBase::GetWrapperImpl(v8::Isolate* isolate,
WrapperInfo* info) {
if (!wrapper_.IsEmpty()) {
return v8::Local<v8::Object>::New(isolate, wrapper_);
}

PerIsolateData* data = PerIsolateData::From(isolate);
v8::Local<v8::ObjectTemplate> templ = data->GetObjectTemplate(info);
if (templ.IsEmpty()) {
templ = template_getter(isolate);
templ = GetObjectTemplateBuilder(isolate).Build();
CHECK(!templ.IsEmpty());
data->SetObjectTemplate(info, templ);
}
Expand Down
21 changes: 6 additions & 15 deletions gin/wrappable.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,32 +53,23 @@ GIN_EXPORT void* FromV8Impl(v8::Isolate* isolate,
template<typename T>
class Wrappable;

class ObjectTemplateBuilder;

// Non-template base class to share code between templates instances.
class GIN_EXPORT WrappableBase {
protected:
typedef v8::Local<v8::ObjectTemplate>(*GetObjectTemplateFunction)(
v8::Isolate*);

WrappableBase();
virtual ~WrappableBase();

v8::Handle<v8::Object> GetWrapperImpl(
v8::Isolate* isolate,
WrapperInfo* wrapper_info,
GetObjectTemplateFunction template_getter);
virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate);

static v8::Local<v8::ObjectTemplate> GetObjectTemplate(v8::Isolate* isolate);
v8::Handle<v8::Object> GetWrapperImpl(v8::Isolate* isolate,
WrapperInfo* wrapper_info);

private:
static void WeakCallback(
const v8::WeakCallbackData<v8::Object, WrappableBase>& data);

v8::Handle<v8::Object> CreateWrapper(
v8::Isolate* isolate,
WrapperInfo* wrapper_info,
GetObjectTemplateFunction template_getter);

v8::Persistent<v8::Object> wrapper_; // Weak

DISALLOW_COPY_AND_ASSIGN(WrappableBase);
Expand All @@ -92,7 +83,7 @@ class Wrappable : public WrappableBase {
// To customize the wrapper created for a subclass, override GetWrapperInfo()
// instead of overriding this function.
v8::Handle<v8::Object> GetWrapper(v8::Isolate* isolate) {
return GetWrapperImpl(isolate, &T::kWrapperInfo, &T::GetObjectTemplate);
return GetWrapperImpl(isolate, &T::kWrapperInfo);
}

protected:
Expand All @@ -107,7 +98,7 @@ class Wrappable : public WrappableBase {
// This converter handles any subclass of Wrappable.
template<typename T>
struct Converter<T*, typename base::enable_if<
base::is_convertible<T*, Wrappable<T>*>::value>::type> {
base::is_convertible<T*, WrappableBase*>::value>::type> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) {
return val->GetWrapper(isolate);
}
Expand Down
63 changes: 55 additions & 8 deletions gin/wrappable_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,49 @@ class MyObject : public Wrappable<MyObject> {
public:
static WrapperInfo kWrapperInfo;

static v8::Local<v8::ObjectTemplate> GetObjectTemplate(v8::Isolate* isolate);

static gin::Handle<MyObject> Create(v8::Isolate* isolate) {
return CreateHandle(isolate, new MyObject());
}

int value() const { return value_; }
void set_value(int value) { value_ = value; }

private:
protected:
MyObject() : value_(0) {}
virtual ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) OVERRIDE;
virtual ~MyObject() {}

private:
int value_;
};

class MyObjectSubclass : public MyObject {
public:
static gin::Handle<MyObjectSubclass> Create(v8::Isolate* isolate) {
return CreateHandle(isolate, new MyObjectSubclass());
}

void SayHello(const std::string& name) {
result = std::string("Hello, ") + name;
}

std::string result;

private:
virtual ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) OVERRIDE {
return MyObject::GetObjectTemplateBuilder(isolate)
.SetMethod("sayHello", &MyObjectSubclass::SayHello);
}

MyObjectSubclass() {
}

virtual ~MyObjectSubclass() {
}
};

class MyObject2 : public Wrappable<MyObject2> {
public:
static WrapperInfo kWrapperInfo;
Expand All @@ -46,11 +73,9 @@ class MyObjectBlink : public Wrappable<MyObjectBlink> {
};

WrapperInfo MyObject::kWrapperInfo = { kEmbedderNativeGin };
v8::Local<v8::ObjectTemplate> MyObject::GetObjectTemplate(
v8::Isolate* isolate) {
return ObjectTemplateBuilder(isolate)
.SetProperty("value", &MyObject::value, &MyObject::set_value)
.Build();
ObjectTemplateBuilder MyObject::GetObjectTemplateBuilder(v8::Isolate* isolate) {
return Wrappable<MyObject>::GetObjectTemplateBuilder(isolate)
.SetProperty("value", &MyObject::value, &MyObject::set_value);
}

WrapperInfo MyObject2::kWrapperInfo = { kEmbedderNativeGin };
Expand Down Expand Up @@ -132,4 +157,26 @@ TEST_F(WrappableTest, GetAndSetProperty) {
EXPECT_EQ(191, obj->value());
}

TEST_F(WrappableTest, WrappableSubclass) {
v8::Isolate* isolate = instance_->isolate();
v8::HandleScope handle_scope(isolate);

gin::Handle<MyObjectSubclass> object(MyObjectSubclass::Create(isolate));
v8::Handle<v8::String> source = StringToV8(isolate,
"(function(obj) {"
"obj.sayHello('Lily');"
"})");
gin::TryCatch try_catch;
v8::Handle<v8::Script> script = v8::Script::New(source);
v8::Handle<v8::Value> val = script->Run();
v8::Handle<v8::Function> func;
EXPECT_TRUE(ConvertFromV8(isolate, val, &func));
v8::Handle<v8::Value> argv[] = {
ConvertToV8(isolate, object.get())
};
func->Call(v8::Undefined(isolate), 1, argv);
EXPECT_FALSE(try_catch.HasCaught());
EXPECT_EQ("Hello, Lily", object->result);
}

} // namespace gin
19 changes: 9 additions & 10 deletions mojo/apps/js/bindings/gl/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,6 @@ gin::Handle<Context> Context::Create(v8::Isolate* isolate, uint64_t encoded,
return gin::CreateHandle(isolate, new Context(encoded, width, height));
}

v8::Local<v8::ObjectTemplate> Context::GetObjectTemplate(
v8::Isolate* isolate) {
return gin::ObjectTemplateBuilder(isolate)
.SetValue("VERTEX_SHADER", GL_VERTEX_SHADER)
.SetMethod("createShader", CreateShader)
.SetMethod("shaderSource", ShaderSource)
.SetMethod("compileShader", CompileShader)
.Build();
}

gin::Handle<Shader> Context::CreateShader(const gin::Arguments& args,
GLenum type) {
gin::Handle<Shader> result;
Expand Down Expand Up @@ -60,6 +50,15 @@ void Context::CompileShader(const gin::Arguments& args,
}
}

gin::ObjectTemplateBuilder Context::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return gin::Wrappable<Context>::GetObjectTemplateBuilder(isolate)
.SetValue("VERTEX_SHADER", GL_VERTEX_SHADER)
.SetMethod("createShader", CreateShader)
.SetMethod("shaderSource", ShaderSource)
.SetMethod("compileShader", CompileShader);
}

Context::Context(uint64_t encoded, int width, int height)
: encoded_(encoded) {
// TODO(aa): When we want to support multiple contexts, we should add
Expand Down
5 changes: 3 additions & 2 deletions mojo/apps/js/bindings/gl/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ class Context : public gin::Wrappable<Context> {
public:
static gin::WrapperInfo kWrapperInfo;

static v8::Local<v8::ObjectTemplate> GetObjectTemplate(v8::Isolate* isolate);

static gin::Handle<Context> Create(v8::Isolate* isolate, uint64_t encoded,
int width, int height);
static gin::Handle<Shader> CreateShader(const gin::Arguments& arguments,
Expand All @@ -40,6 +38,9 @@ class Context : public gin::Wrappable<Context> {
gin::Handle<Shader> shader);

private:
virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) OVERRIDE;

Context(uint64_t encoded, int width, int height);

uint64_t encoded_;
Expand Down

0 comments on commit 13c977e

Please sign in to comment.