blob: b0aa8fab1bdc4db895705d2154089547fc9c91c0 [file] [log] [blame]
// Copyright 2015 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 "base/at_exit.h"
#include "base/base_paths.h"
#include "base/base_switches.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/process/process.h"
#include "base/thread_task_runner_handle.h"
#include "mojo/application/public/cpp/application_connection.h"
#include "mojo/application/public/cpp/application_delegate.h"
#include "mojo/application/public/cpp/application_impl.h"
#include "mojo/application/public/cpp/interface_factory.h"
#include "mojo/application/public/interfaces/application_manager.mojom.h"
#include "mojo/common/weak_binding_set.h"
#include "mojo/converters/network/network_type_converters.h"
#include "mojo/runner/child/test_native_main.h"
#include "mojo/runner/init.h"
#include "mojo/shell/application_manager_apptests.mojom.h"
#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h"
using mojo::shell::test::mojom::Driver;
namespace {
class TargetApplicationDelegate : public mojo::ApplicationDelegate,
public mojo::InterfaceFactory<Driver>,
public Driver {
public:
TargetApplicationDelegate() : app_(nullptr), weak_factory_(this) {}
~TargetApplicationDelegate() override {}
private:
// mojo::ApplicationDelegate:
void Initialize(mojo::ApplicationImpl* app) override {
app_ = app;
mojo::shell::mojom::ApplicationManagerPtr application_manager;
app_->ConnectToService("mojo:shell", &application_manager);
base::FilePath target_path;
CHECK(base::PathService::Get(base::DIR_EXE, &target_path));
#if defined(OS_WIN)
target_path = target_path.Append(
FILE_PATH_LITERAL("application_manager_apptest_target.exe"));
#else
target_path = target_path.Append(
FILE_PATH_LITERAL("application_manager_apptest_target"));
#endif
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);
}
if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk"))
child_command_line.AppendSwitch("use-new-edk");
mojo::embedder::HandlePassingInformation handle_passing_info;
// Create the channel to be shared with the target process.
mojo::embedder::PlatformChannelPair platform_channel_pair;
// Give one end to the shell so that it can create an instance.
mojo::embedder::ScopedPlatformHandle platform_channel =
platform_channel_pair.PassServerHandle();
mojo::ScopedMessagePipeHandle handle(mojo::embedder::CreateChannel(
platform_channel.Pass(),
base::Bind(&TargetApplicationDelegate::DidCreateChannel,
weak_factory_.GetWeakPtr()),
base::ThreadTaskRunnerHandle::Get()));
mojo::CapabilityFilterPtr filter(mojo::CapabilityFilter::New());
mojo::Array<mojo::String> test_interfaces;
test_interfaces.push_back(
mojo::shell::test::mojom::CreateInstanceForHandleTest::Name_);
filter->filter.insert("mojo:mojo_shell_apptests", test_interfaces.Pass());
application_manager->CreateInstanceForHandle(
mojo::ScopedHandle(mojo::Handle(handle.release().value())),
"exe:application_manager_apptest_target",
filter.Pass());
// Put the other end on the command line used to launch the target.
platform_channel_pair.PrepareToPassClientHandleToChildProcess(
&child_command_line, &handle_passing_info);
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
target_ = base::LaunchProcess(child_command_line, options);
}
bool ConfigureIncomingConnection(
mojo::ApplicationConnection* connection) override {
connection->AddService<Driver>(this);
return true;
}
// mojo::InterfaceFactory<Driver>:
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<Driver> request) override {
bindings_.AddBinding(this, request.Pass());
}
// Driver:
void QuitDriver() override {
target_.Terminate(0, false);
app_->Quit();
}
void DidCreateChannel(mojo::embedder::ChannelInfo* channel_info) {}
mojo::ApplicationImpl* app_;
base::Process target_;
mojo::WeakBindingSet<Driver> bindings_;
base::WeakPtrFactory<TargetApplicationDelegate> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(TargetApplicationDelegate);
};
} // namespace
int main(int argc, char** argv) {
base::AtExitManager at_exit;
base::CommandLine::Init(argc, argv);
mojo::runner::InitializeLogging();
TargetApplicationDelegate delegate;
return mojo::runner::TestNativeMain(&delegate);
}