blob: a068902a3bc1fc6f4e746d701e91a322318a4978 [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/java/gin_java_bridge_object.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "content/public/common/content_features.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/java/gin_java_function_invocation_helper.h"
#include "gin/function_template.h"
#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "v8/include/cppgc/allocation.h"
#include "v8/include/v8-context.h"
#include "v8/include/v8-cppgc.h"
#include "v8/include/v8-function.h"
#include "v8/include/v8-local-handle.h"
namespace content {
// static
GinJavaBridgeObject* GinJavaBridgeObject::InjectNamed(
blink::WebLocalFrame* frame,
const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
const std::string& object_name,
GinJavaBridgeDispatcher::ObjectID object_id) {
v8::Isolate* isolate = frame->GetAgentGroupScheduler()->Isolate();
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = frame->MainWorldScriptContext();
if (context.IsEmpty()) {
return nullptr;
}
auto* object = cppgc::MakeGarbageCollected<GinJavaBridgeObject>(
isolate->GetCppHeap()->GetAllocationHandle(), isolate, dispatcher,
object_id);
v8::Context::Scope context_scope(context);
v8::Local<v8::Object> global = context->Global();
v8::Local<v8::Value> controller;
if (!object->GetWrapper(isolate).ToLocal(&controller)) {
return nullptr;
}
global->Set(context, gin::StringToV8(isolate, object_name), controller)
.Check();
return object;
}
// static
GinJavaBridgeObject* GinJavaBridgeObject::InjectAnonymous(
blink::WebLocalFrame* frame,
const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
GinJavaBridgeDispatcher::ObjectID object_id) {
v8::Isolate* isolate = frame->GetAgentGroupScheduler()->Isolate();
return cppgc::MakeGarbageCollected<GinJavaBridgeObject>(
isolate->GetCppHeap()->GetAllocationHandle(), isolate, dispatcher,
object_id);
}
GinJavaBridgeObject::GinJavaBridgeObject(
v8::Isolate* isolate,
const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
GinJavaBridgeDispatcher::ObjectID object_id)
: dispatcher_(dispatcher), object_id_(object_id), template_cache_(isolate) {
dispatcher_->GetRemoteObjectHost()->GetObject(
object_id, remote_.BindNewPipeAndPassReceiver());
}
GinJavaBridgeObject::~GinJavaBridgeObject() = default;
void GinJavaBridgeObject::Dispose() {
if (dispatcher_) {
dispatcher_->OnGinJavaBridgeObjectDeleted(this);
}
}
const gin::WrapperInfo* GinJavaBridgeObject::wrapper_info() const {
return &kWrapperInfo;
}
gin::ObjectTemplateBuilder GinJavaBridgeObject::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return gin::WrappableWithNamedPropertyInterceptor<
GinJavaBridgeObject>::GetObjectTemplateBuilder(isolate)
.template AddNamedPropertyInterceptor<kWrapperInfo.pointer_tag>();
}
v8::Local<v8::Value> GinJavaBridgeObject::GetNamedProperty(
v8::Isolate* isolate,
const std::string& property) {
if (!base::Contains(known_methods_, property)) {
if (!dispatcher_) {
return v8::Local<v8::Value>();
}
if (remote_) {
bool result = false;
remote_->HasMethod(property, &result);
known_methods_[property] = result;
}
}
if (known_methods_[property]) {
return GetFunctionTemplate(isolate, property)
->GetFunction(isolate->GetCurrentContext())
.FromMaybe(v8::Local<v8::Value>());
} else {
return v8::Local<v8::Value>();
}
}
std::vector<std::string> GinJavaBridgeObject::EnumerateNamedProperties(
v8::Isolate* isolate) {
std::vector<std::string> method_names;
if (remote_) {
remote_->GetMethods(&method_names);
}
return method_names;
}
v8::Local<v8::FunctionTemplate> GinJavaBridgeObject::GetFunctionTemplate(
v8::Isolate* isolate,
const std::string& name) {
v8::Local<v8::FunctionTemplate> function_template = template_cache_.Get(name);
if (!function_template.IsEmpty()) {
return function_template;
}
function_template = gin::CreateFunctionTemplate(
isolate,
base::BindRepeating(
&GinJavaFunctionInvocationHelper::Invoke,
base::Owned(new GinJavaFunctionInvocationHelper(name, dispatcher_))));
template_cache_.Set(name, function_template);
return function_template;
}
mojom::GinJavaBridgeRemoteObject* GinJavaBridgeObject::GetRemote() {
if (!remote_) {
// non-mojo case.
return nullptr;
}
return remote_.get();
}
} // namespace content