blob: a612d3376dc5a0e5300e37134a4a5a27b0753109 [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 "services/service_manager/tests/util.h"
#include "base/base_paths.h"
#include "base/base_switches.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/process/process.h"
#include "base/run_loop.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/interfaces/connector.mojom.h"
#include "services/service_manager/public/interfaces/service_factory.mojom.h"
#include "services/service_manager/runner/common/switches.h"
namespace service_manager {
namespace test {
namespace {
void GrabConnectResult(base::RunLoop* loop,
mojom::ConnectResult* out_result,
mojom::ConnectResult result,
const Identity& resolved_identity) {
loop->Quit();
*out_result = result;
}
} // namespace
mojom::ConnectResult LaunchAndConnectToProcess(
const std::string& target_exe_name,
const Identity& target,
service_manager::Connector* connector,
base::Process* process) {
base::FilePath target_path;
CHECK(base::PathService::Get(base::DIR_EXE, &target_path));
target_path = target_path.AppendASCII(target_exe_name);
base::CommandLine child_command_line(target_path);
// Forward the wait-for-debugger flag but nothing else - we don't want to
// stamp on the platform-channel flag.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kWaitForDebugger)) {
child_command_line.AppendSwitch(::switches::kWaitForDebugger);
}
// Create the channel to be shared with the target process. Pass one end
// on the command line.
mojo::edk::PlatformChannelPair platform_channel_pair;
mojo::edk::HandlePassingInformation handle_passing_info;
platform_channel_pair.PrepareToPassClientHandleToChildProcess(
&child_command_line, &handle_passing_info);
mojo::edk::PendingProcessConnection pending_process;
std::string token;
mojo::ScopedMessagePipeHandle pipe =
pending_process.CreateMessagePipe(&token);
child_command_line.AppendSwitchASCII(switches::kServicePipeToken, token);
service_manager::mojom::ServicePtr client;
client.Bind(mojo::InterfacePtrInfo<service_manager::mojom::Service>(
std::move(pipe), 0u));
service_manager::mojom::PIDReceiverPtr receiver;
connector->StartService(target, std::move(client), MakeRequest(&receiver));
mojom::ConnectResult result;
{
base::RunLoop loop;
Connector::TestApi test_api(connector);
test_api.SetStartServiceCallback(
base::Bind(&GrabConnectResult, &loop, &result));
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
loop.Run();
}
base::LaunchOptions options;
#if defined(OS_WIN)
options.handles_to_inherit = &handle_passing_info;
#elif defined(OS_POSIX)
options.fds_to_remap = &handle_passing_info;
#endif
*process = base::LaunchProcess(child_command_line, options);
DCHECK(process->IsValid());
receiver->SetPID(process->Pid());
pending_process.Connect(
process->Handle(),
mojo::edk::ConnectionParams(platform_channel_pair.PassServerHandle()));
return result;
}
} // namespace test
} // namespace service_manager