blob: 62034155c026b0e31a755c2b22697adf63019d50 [file] [log] [blame]
// Copyright 2016 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 <memory>
#include "base/bind.h"
#include "base/guid.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/service_manager/public/c/main.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_factory.h"
#include "services/service_manager/public/cpp/service.h"
#include "services/service_manager/public/cpp/service_context.h"
#include "services/service_manager/public/cpp/service_runner.h"
#include "services/service_manager/public/interfaces/connector.mojom.h"
#include "services/service_manager/tests/connect/connect_test.mojom.h"
namespace service_manager {
namespace {
void QuitLoop(base::RunLoop* loop,
mojom::ConnectResult* out_result,
Identity* out_resolved_identity,
mojom::ConnectResult result,
const Identity& resolved_identity) {
loop->Quit();
*out_result = result;
*out_resolved_identity = resolved_identity;
}
void ReceiveString(std::string* string,
base::RunLoop* loop,
const std::string& response) {
*string = response;
loop->Quit();
}
} // namespace
using GetTitleCallback = test::mojom::ConnectTestService::GetTitleCallback;
class ConnectTestApp : public Service,
public InterfaceFactory<test::mojom::ConnectTestService>,
public InterfaceFactory<test::mojom::StandaloneApp>,
public InterfaceFactory<test::mojom::BlockedInterface>,
public InterfaceFactory<test::mojom::UserIdTest>,
public test::mojom::ConnectTestService,
public test::mojom::StandaloneApp,
public test::mojom::BlockedInterface,
public test::mojom::UserIdTest {
public:
ConnectTestApp() {}
~ConnectTestApp() override {}
private:
// service_manager::Service:
void OnStart() override {
bindings_.set_connection_error_handler(
base::Bind(&ConnectTestApp::OnConnectionError,
base::Unretained(this)));
standalone_bindings_.set_connection_error_handler(
base::Bind(&ConnectTestApp::OnConnectionError,
base::Unretained(this)));
registry_.AddInterface<test::mojom::ConnectTestService>(this);
registry_.AddInterface<test::mojom::StandaloneApp>(this);
registry_.AddInterface<test::mojom::BlockedInterface>(this);
registry_.AddInterface<test::mojom::UserIdTest>(this);
}
void OnBindInterface(const ServiceInfo& source_info,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override {
registry_.BindInterface(source_info.identity, interface_name,
std::move(interface_pipe));
}
// InterfaceFactory<test::mojom::ConnectTestService>:
void Create(const Identity& remote_identity,
test::mojom::ConnectTestServiceRequest request) override {
bindings_.AddBinding(this, std::move(request));
test::mojom::ConnectionStatePtr state(test::mojom::ConnectionState::New());
state->connection_remote_name = remote_identity.name();
state->connection_remote_userid = remote_identity.user_id();
state->initialize_local_name = context()->identity().name();
state->initialize_userid = context()->identity().user_id();
context()->connector()->BindInterface(remote_identity, &caller_);
caller_->ConnectionAccepted(std::move(state));
}
// InterfaceFactory<test::mojom::StandaloneApp>:
void Create(const Identity& remote_identity,
test::mojom::StandaloneAppRequest request) override {
standalone_bindings_.AddBinding(this, std::move(request));
}
// InterfaceFactory<test::mojom::BlockedInterface>:
void Create(const Identity& remote_identity,
test::mojom::BlockedInterfaceRequest request) override {
blocked_bindings_.AddBinding(this, std::move(request));
}
// InterfaceFactory<test::mojom::UserIdTest>:
void Create(const Identity& remote_identity,
test::mojom::UserIdTestRequest request) override {
user_id_test_bindings_.AddBinding(this, std::move(request));
}
// test::mojom::ConnectTestService:
void GetTitle(const GetTitleCallback& callback) override {
callback.Run("APP");
}
void GetInstance(const GetInstanceCallback& callback) override {
callback.Run(context()->identity().instance());
}
// test::mojom::StandaloneApp:
void ConnectToAllowedAppInBlockedPackage(
const ConnectToAllowedAppInBlockedPackageCallback& callback) override {
base::RunLoop run_loop;
test::mojom::ConnectTestServicePtr test_service;
context()->connector()->BindInterface("connect_test_a", &test_service);
test_service.set_connection_error_handler(
base::Bind(&ConnectTestApp::OnConnectionBlocked, base::Unretained(this),
callback, &run_loop));
test_service->GetTitle(
base::Bind(&ConnectTestApp::OnGotTitle, base::Unretained(this),
callback, &run_loop));
{
// This message is dispatched as a task on the same run loop, so we need
// to allow nesting in order to pump additional signals.
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
run_loop.Run();
}
}
void ConnectToClassInterface(
const ConnectToClassInterfaceCallback& callback) override {
test::mojom::ClassInterfacePtr class_interface;
context()->connector()->BindInterface("connect_test_class_app",
&class_interface);
std::string ping_response;
{
base::RunLoop loop;
class_interface->Ping(base::Bind(&ReceiveString, &ping_response, &loop));
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
loop.Run();
}
test::mojom::ConnectTestServicePtr service;
context()->connector()->BindInterface("connect_test_class_app", &service);
std::string title_response;
{
base::RunLoop loop;
service->GetTitle(base::Bind(&ReceiveString, &title_response, &loop));
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
loop.Run();
}
callback.Run(ping_response, title_response);
}
// test::mojom::BlockedInterface:
void GetTitleBlocked(const GetTitleBlockedCallback& callback) override {
callback.Run("Called Blocked Interface!");
}
// test::mojom::UserIdTest:
void ConnectToClassAppAsDifferentUser(
const service_manager::Identity& target,
const ConnectToClassAppAsDifferentUserCallback& callback) override {
context()->connector()->StartService(target);
mojom::ConnectResult result;
Identity resolved_identity;
{
base::RunLoop loop;
Connector::TestApi test_api(context()->connector());
test_api.SetStartServiceCallback(
base::Bind(&QuitLoop, &loop, &result, &resolved_identity));
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
loop.Run();
}
callback.Run(static_cast<int32_t>(result), resolved_identity);
}
void OnConnectionBlocked(
const ConnectToAllowedAppInBlockedPackageCallback& callback,
base::RunLoop* run_loop) {
callback.Run("uninitialized");
run_loop->Quit();
}
void OnGotTitle(
const ConnectToAllowedAppInBlockedPackageCallback& callback,
base::RunLoop* run_loop,
const std::string& title) {
callback.Run(title);
run_loop->Quit();
}
void OnConnectionError() {
if (bindings_.empty() && standalone_bindings_.empty())
base::MessageLoop::current()->QuitWhenIdle();
}
BinderRegistry registry_;
mojo::BindingSet<test::mojom::ConnectTestService> bindings_;
mojo::BindingSet<test::mojom::StandaloneApp> standalone_bindings_;
mojo::BindingSet<test::mojom::BlockedInterface> blocked_bindings_;
mojo::BindingSet<test::mojom::UserIdTest> user_id_test_bindings_;
test::mojom::ExposedInterfacePtr caller_;
DISALLOW_COPY_AND_ASSIGN(ConnectTestApp);
};
} // namespace service_manager
MojoResult ServiceMain(MojoHandle service_request_handle) {
service_manager::ServiceRunner runner(new service_manager::ConnectTestApp);
return runner.Run(service_request_handle);
}