blob: 352ee01b5fe1b921f1375a2e87b5178f30df006d [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/mojo/interface_provider_js_wrapper.h"
#include <memory>
#include <utility>
#include "content/public/common/service_names.mojom.h"
#include "mojo/edk/js/handle.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
namespace content {
gin::WrapperInfo InterfaceProviderJsWrapper::kWrapperInfo = {
gin::kEmbedderNativeGin};
const char InterfaceProviderJsWrapper::kPerFrameModuleName[] =
"content/public/renderer/frame_interfaces";
const char InterfaceProviderJsWrapper::kPerProcessModuleName[] =
"content/public/renderer/interfaces";
InterfaceProviderJsWrapper::~InterfaceProviderJsWrapper() {
}
// static
gin::Handle<InterfaceProviderJsWrapper> InterfaceProviderJsWrapper::Create(
v8::Isolate* isolate,
v8::Local<v8::Context> context,
service_manager::Connector* connector) {
return gin::CreateHandle(
isolate, new InterfaceProviderJsWrapper(isolate, context,
connector->GetWeakPtr()));
}
// static
gin::Handle<InterfaceProviderJsWrapper> InterfaceProviderJsWrapper::Create(
v8::Isolate* isolate,
v8::Local<v8::Context> context,
service_manager::InterfaceProvider* remote_interfaces) {
return gin::CreateHandle(
isolate,
new InterfaceProviderJsWrapper(
isolate, context,
remote_interfaces->GetWeakPtr()));
}
gin::ObjectTemplateBuilder
InterfaceProviderJsWrapper::GetObjectTemplateBuilder(v8::Isolate* isolate) {
return Wrappable<InterfaceProviderJsWrapper>::GetObjectTemplateBuilder(
isolate)
.SetMethod("getInterface",
&InterfaceProviderJsWrapper::GetInterface)
.SetMethod("addInterfaceOverrideForTesting",
&InterfaceProviderJsWrapper::AddOverrideForTesting)
.SetMethod("clearInterfaceOverridesForTesting",
&InterfaceProviderJsWrapper::ClearOverridesForTesting);
}
mojo::Handle InterfaceProviderJsWrapper::GetInterface(
const std::string& interface_name) {
mojo::MessagePipe pipe;
if (connector_) {
connector_->BindInterface(
service_manager::Identity(mojom::kBrowserServiceName,
service_manager::mojom::kInheritUserID),
interface_name, std::move(pipe.handle0));
} else if (remote_interfaces_) {
remote_interfaces_->GetInterface(
interface_name, std::move(pipe.handle0));
}
return pipe.handle1.release();
}
void InterfaceProviderJsWrapper::AddOverrideForTesting(
const std::string& interface_name,
v8::Local<v8::Function> service_factory) {
ScopedJsFactory factory(v8::Isolate::GetCurrent(), service_factory);
BindCallback callback = base::Bind(&InterfaceProviderJsWrapper::CallJsFactory,
weak_factory_.GetWeakPtr(), factory);
if (remote_interfaces_) {
service_manager::InterfaceProvider::TestApi test_api(
remote_interfaces_.get());
test_api.SetBinderForName(interface_name, callback);
} else if (connector_) {
service_manager::Connector::TestApi test_api(connector_.get());
test_api.OverrideBinderForTesting(mojom::kBrowserServiceName,
interface_name, callback);
}
}
void InterfaceProviderJsWrapper::ClearOverridesForTesting() {
if (remote_interfaces_) {
service_manager::InterfaceProvider::TestApi test_api(
remote_interfaces_.get());
test_api.ClearBinders();
} else if (connector_) {
service_manager::Connector::TestApi test_api(connector_.get());
test_api.ClearBinderOverrides();
}
}
InterfaceProviderJsWrapper::InterfaceProviderJsWrapper(
v8::Isolate* isolate,
v8::Local<v8::Context> context,
base::WeakPtr<service_manager::Connector> connector)
: isolate_(isolate),
context_(isolate, context),
connector_(connector),
weak_factory_(this) {
context_.SetWeak(this, &InterfaceProviderJsWrapper::ClearContext,
v8::WeakCallbackType::kParameter);
}
InterfaceProviderJsWrapper::InterfaceProviderJsWrapper(
v8::Isolate* isolate,
v8::Local<v8::Context> context,
base::WeakPtr<service_manager::InterfaceProvider> remote_interfaces)
: isolate_(isolate),
context_(isolate, context),
remote_interfaces_(remote_interfaces),
weak_factory_(this) {
context_.SetWeak(this, &InterfaceProviderJsWrapper::ClearContext,
v8::WeakCallbackType::kParameter);
}
void InterfaceProviderJsWrapper::CallJsFactory(
const ScopedJsFactory& factory,
mojo::ScopedMessagePipeHandle pipe) {
if (context_.IsEmpty())
return;
v8::HandleScope handle_scope(isolate_);
v8::Local<v8::Context> context = context_.Get(isolate_);
v8::Context::Scope context_scope(context);
v8::Local<v8::Value> argv[] = {
gin::ConvertToV8(isolate_, mojo::Handle(pipe.release().value()))};
blink::WebLocalFrame::FrameForContext(context)
->CallFunctionEvenIfScriptDisabled(factory.Get(isolate_),
v8::Undefined(isolate_), 1, argv);
}
// static
void InterfaceProviderJsWrapper::ClearContext(
const v8::WeakCallbackInfo<InterfaceProviderJsWrapper>& data) {
InterfaceProviderJsWrapper* registry = data.GetParameter();
registry->context_.Reset();
}
} // namespace content