1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/renderer/java/gin_java_bridge_object.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
8d4eceafabf754f25111843103617cde83d31a0c1Mikhail Naganov#include "content/common/android/gin_java_bridge_errors.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/common/android/gin_java_bridge_value.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/renderer/v8_value_converter.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/renderer/java/gin_java_bridge_value_converter.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "gin/function_template.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "third_party/WebKit/public/web/WebKit.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace content {
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kMethodInvocationErrorMessage[] =
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    "Java bridge method invocation error";
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)GinJavaBridgeObject* GinJavaBridgeObject::InjectNamed(
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    blink::WebFrame* frame,
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& object_name,
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GinJavaBridgeDispatcher::ObjectID object_id) {
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  v8::Isolate* isolate = blink::mainThreadIsolate();
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  v8::HandleScope handle_scope(isolate);
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (context.IsEmpty())
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return NULL;
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GinJavaBridgeObject* object =
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new GinJavaBridgeObject(isolate, dispatcher, object_id);
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  v8::Context::Scope context_scope(context);
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  v8::Handle<v8::Object> global = context->Global();
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  gin::Handle<GinJavaBridgeObject> controller =
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      gin::CreateHandle(isolate, object);
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // WrappableBase instance deletes itself in case of a wrapper
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // creation failure, thus there is no need to delete |object|.
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (controller.IsEmpty())
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return NULL;
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  global->Set(gin::StringToV8(isolate, object_name), controller.ToV8());
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return object;
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)GinJavaBridgeObject* GinJavaBridgeObject::InjectAnonymous(
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GinJavaBridgeDispatcher::ObjectID object_id) {
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return new GinJavaBridgeObject(
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      blink::mainThreadIsolate(), dispatcher, object_id);
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)GinJavaBridgeObject::GinJavaBridgeObject(
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    v8::Isolate* isolate,
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GinJavaBridgeDispatcher::ObjectID object_id)
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : gin::NamedPropertyInterceptor(isolate, this),
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      dispatcher_(dispatcher),
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      object_id_(object_id),
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      converter_(new GinJavaBridgeValueConverter()) {
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)GinJavaBridgeObject::~GinJavaBridgeObject() {
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (dispatcher_)
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    dispatcher_->OnGinJavaBridgeObjectDeleted(object_id_);
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gin::ObjectTemplateBuilder GinJavaBridgeObject::GetObjectTemplateBuilder(
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    v8::Isolate* isolate) {
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return gin::Wrappable<GinJavaBridgeObject>::GetObjectTemplateBuilder(isolate)
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      .AddNamedPropertyInterceptor();
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)v8::Local<v8::Value> GinJavaBridgeObject::GetNamedProperty(
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    v8::Isolate* isolate,
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& property) {
8686e749a1070de1c60907c5142944a7b6977920d9Mikhail Naganov  std::map<std::string, bool>::iterator method_pos =
8786e749a1070de1c60907c5142944a7b6977920d9Mikhail Naganov      known_methods_.find(property);
8886e749a1070de1c60907c5142944a7b6977920d9Mikhail Naganov  if (method_pos == known_methods_.end()) {
8986e749a1070de1c60907c5142944a7b6977920d9Mikhail Naganov    if (!dispatcher_) {
9086e749a1070de1c60907c5142944a7b6977920d9Mikhail Naganov      return v8::Local<v8::Value>();
9186e749a1070de1c60907c5142944a7b6977920d9Mikhail Naganov    }
9286e749a1070de1c60907c5142944a7b6977920d9Mikhail Naganov    known_methods_[property] = dispatcher_->HasJavaMethod(object_id_, property);
9386e749a1070de1c60907c5142944a7b6977920d9Mikhail Naganov  }
9486e749a1070de1c60907c5142944a7b6977920d9Mikhail Naganov  if (known_methods_[property]) {
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return gin::CreateFunctionTemplate(
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               isolate,
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               base::Bind(&GinJavaBridgeObject::InvokeMethod,
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          base::Unretained(this),
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          property))->GetFunction();
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return v8::Local<v8::Value>();
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::vector<std::string> GinJavaBridgeObject::EnumerateNamedProperties(
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    v8::Isolate* isolate) {
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::set<std::string> method_names;
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (dispatcher_)
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    dispatcher_->GetJavaMethods(object_id_, &method_names);
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return std::vector<std::string> (method_names.begin(), method_names.end());
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)v8::Handle<v8::Value> GinJavaBridgeObject::InvokeMethod(
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& name,
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    gin::Arguments* args) {
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!dispatcher_) {
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        args->isolate(), kMethodInvocationErrorMessage)));
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return v8::Undefined(args->isolate());
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::ListValue arguments;
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  {
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    v8::HandleScope handle_scope(args->isolate());
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    v8::Handle<v8::Context> context = args->isolate()->GetCurrentContext();
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    v8::Handle<v8::Value> val;
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    while (args->GetNext(&val)) {
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_ptr<base::Value> arg(converter_->FromV8Value(val, context));
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (arg.get()) {
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        arguments.Append(arg.release());
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      } else {
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        arguments.Append(base::Value::CreateNullValue());
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
137d4eceafabf754f25111843103617cde83d31a0c1Mikhail Naganov  GinJavaBridgeError error;
138d4eceafabf754f25111843103617cde83d31a0c1Mikhail Naganov  scoped_ptr<base::Value> result = dispatcher_->InvokeJavaMethod(
139d4eceafabf754f25111843103617cde83d31a0c1Mikhail Naganov      object_id_, name, arguments, &error);
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!result.get()) {
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
142d4eceafabf754f25111843103617cde83d31a0c1Mikhail Naganov        args->isolate(), GinJavaBridgeErrorToString(error))));
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return v8::Undefined(args->isolate());
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!result->IsType(base::Value::TYPE_BINARY)) {
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return converter_->ToV8Value(result.get(),
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 args->isolate()->GetCurrentContext());
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<const GinJavaBridgeValue> gin_value =
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GinJavaBridgeValue::FromValue(result.get());
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (gin_value->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID)) {
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GinJavaBridgeObject* result = NULL;
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GinJavaBridgeDispatcher::ObjectID object_id;
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (gin_value->GetAsObjectID(&object_id)) {
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      result = dispatcher_->GetObject(object_id);
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (result) {
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      gin::Handle<GinJavaBridgeObject> controller =
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          gin::CreateHandle(args->isolate(), result);
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (controller.IsEmpty())
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return v8::Undefined(args->isolate());
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return controller.ToV8();
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (gin_value->IsType(GinJavaBridgeValue::TYPE_NONFINITE)) {
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    float float_value;
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    gin_value->GetAsNonFinite(&float_value);
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return v8::Number::New(args->isolate(), float_value);
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return v8::Undefined(args->isolate());
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gin::WrapperInfo GinJavaBridgeObject::kWrapperInfo = {gin::kEmbedderNativeGin};
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace content
176