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