Commit 48799d72 authored by ben's avatar ben Committed by Commit bot

Allow mojo_runner to connect to arbitrary executables.

- Introduces a new scheme "exe" which loads an executable alongside mojo_runner. TODO is some more security checking around this to prevent arbitrary apps from launching executables but since this is implemented in mojo_runner it's not in any production code right now.
- Includes an apptest of a .mojo app that connects to an executable and binds a service provided by it.
- Creates a new child library that makes it easy to bring up a runner controller thread in an arbitrary executable.

R=jam@chromium.org
http://crbug.com/548694

Review URL: https://codereview.chromium.org/1419293003

Cr-Commit-Position: refs/heads/master@{#357034}
parent 1c318713
......@@ -102,7 +102,4 @@ source_set("test_support") {
if (is_android) {
data_deps += [ "//mojo/android" ]
}
if (!is_component_build) {
data_deps += [ "//mojo/runner" ]
}
}
......@@ -19,22 +19,32 @@ URLResolver::URLResolver(const GURL& mojo_base_url)
DCHECK(mojo_base_url_.is_valid());
// Needed to treat first component of mojo URLs as host, not path.
url::AddStandardScheme("mojo", url::SCHEME_WITHOUT_AUTHORITY);
url::AddStandardScheme("exe", url::SCHEME_WITHOUT_AUTHORITY);
}
URLResolver::~URLResolver() {
}
GURL URLResolver::ResolveMojoURL(const GURL& mojo_url) const {
if (mojo_url.scheme() != "mojo") {
if (mojo_url.SchemeIs("mojo")) {
// It's still a mojo: URL, use the default mapping scheme.
std::string query;
GURL base_url = shell::GetBaseURLAndQuery(mojo_url, &query);
const std::string host = base_url.host();
return mojo_base_url_.Resolve(host + "/" + host + ".mojo" + query);
} else if (mojo_url.SchemeIs("exe")) {
#if defined OS_WIN
std::string extension = ".exe";
#else
std::string extension;
#endif
std::string query;
GURL base_url = shell::GetBaseURLAndQuery(mojo_url, &query);
return mojo_base_url_.Resolve(base_url.host() + extension);
} else {
// The mapping has produced some sort of non-mojo: URL - file:, http:, etc.
return mojo_url;
}
// It's still a mojo: URL, use the default mapping scheme.
std::string query;
GURL base_url = shell::GetBaseURLAndQuery(mojo_url, &query);
const std::string host = base_url.host();
return mojo_base_url_.Resolve(host + "/" + host + ".mojo" + query);
}
} // namespace fetcher
......
......@@ -16,6 +16,7 @@ group("runner") {
deps = [
":mojo_runner",
"//mojo/runner/child",
]
}
......@@ -94,18 +95,14 @@ executable("mojo_runner") {
}
}
source_set("in_process_native_runner") {
source_set("init") {
sources = [
"in_process_native_runner.cc",
"in_process_native_runner.h",
]
public_deps = [
":native_application_support",
"//mojo/shell",
"init.cc",
"init.h",
]
deps = [
":switches",
"//base",
]
}
......@@ -118,8 +115,8 @@ source_set("lib") {
"child_process_host.h",
"context.cc",
"context.h",
"init.cc",
"init.h",
"in_process_native_runner.cc",
"in_process_native_runner.h",
"out_of_process_native_runner.cc",
"out_of_process_native_runner.h",
"scoped_user_data_dir.cc",
......@@ -131,8 +128,7 @@ source_set("lib") {
]
deps = [
":child_process_bindings",
":in_process_native_runner",
":init",
":native_application_support",
"//base",
"//base/third_party/dynamic_annotations",
......@@ -142,6 +138,7 @@ source_set("lib") {
"//mojo/application/public/cpp",
"//mojo/message_pump",
"//mojo/package_manager",
"//mojo/runner/child:interfaces",
"//mojo/services/network/public/interfaces",
"//mojo/services/tracing/public/cpp",
"//mojo/services/tracing/public/interfaces",
......@@ -165,6 +162,7 @@ source_set("lib") {
}
public_deps = [
":init",
":switches",
]
......@@ -419,18 +417,6 @@ if (is_android) {
}
}
mojom("child_process_bindings") {
sources = [
"child_process.mojom",
]
deps = [
"//mojo/application/public/interfaces",
]
import_dirs = [ "//mojo/services" ]
}
test("mojo_runner_unittests") {
sources = [
"../fetcher/about_fetcher_unittest.cc",
......@@ -451,7 +437,6 @@ test("mojo_runner_unittests") {
]
deps = [
":in_process_native_runner",
":lib",
"//base",
"//base:i18n",
......
# 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.
import("//mojo/public/mojo_application.gni")
import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni")
group("child") {
testonly = true
deps = [
":lib",
":apptests",
]
}
source_set("lib") {
sources = [
"runner_connection.cc",
"runner_connection.h",
]
deps = [
":interfaces",
"//base",
"//mojo/application/public/interfaces",
"//mojo/message_pump",
"//third_party/mojo/src/mojo/edk/system",
]
}
mojom("interfaces") {
sources = [
"child_controller.mojom",
]
deps = [
"//mojo/application/public/interfaces",
]
import_dirs = [ "//mojo/services" ]
}
mojom("apptest_interfaces") {
sources = [
"test_native_service.mojom",
]
deps = [
"//mojo/application/public/interfaces",
]
import_dirs = [ "//mojo/services" ]
}
mojo_native_application("apptests") {
output_name = "mojo_runner_child_apptest"
testonly = true
sources = [
"native_apptest.cc",
]
deps = [
":apptest_interfaces",
"//base",
"//base/test:test_config",
"//mojo/application/public/cpp:sources",
"//mojo/application/public/cpp:test_support",
"//mojo/common:common_base",
"//mojo/converters/network:network",
]
data_deps = [
":native_target",
]
}
executable("native_target") {
output_name = "mojo_runner_child_apptest_native_target"
testonly = true
sources = [
"native_apptest_target.cc",
]
deps = [
":apptest_interfaces",
":lib",
"//base",
"//mojo/application/public/cpp",
"//mojo/application/public/interfaces",
"//mojo/common:common_base",
"//mojo/message_pump",
"//mojo/runner:init",
"//third_party/mojo/src/mojo/edk/embedder:embedder",
]
}
// 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/bind.h"
#include "base/macros.h"
#include "mojo/application/public/cpp/application_impl.h"
#include "mojo/application/public/cpp/application_test_base.h"
#include "mojo/converters/network/network_type_converters.h"
#include "mojo/runner/child/test_native_service.mojom.h"
namespace mojo {
namespace runner {
namespace {
void InvertCallback(bool* result, bool from_native) {
*result = from_native;
}
} // namespace
using NativeAppTest = mojo::test::ApplicationTestBase;
TEST_F(NativeAppTest, Connect) {
test::TestNativeServicePtr native_service;
application_impl()->ConnectToService(
mojo::URLRequest::From(
std::string("exe:mojo_runner_child_apptest_native_target")),
&native_service);
bool result = false;
native_service->Invert(
true, base::Bind(&InvertCallback, base::Unretained(&result)));
native_service.WaitForIncomingResponse();
EXPECT_FALSE(result);
native_service->Invert(
false, base::Bind(&InvertCallback, base::Unretained(&result)));
native_service.WaitForIncomingResponse();
EXPECT_TRUE(result);
}
} // namespace runner
} // namespace mojo
// 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 <windows.h>
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/debug/stack_trace.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/process/launch.h"
#include "base/threading/thread.h"
#include "build/build_config.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.mojom.h"
#include "mojo/common/weak_binding_set.h"
#include "mojo/message_pump/message_pump_mojo.h"
#include "mojo/runner/child/runner_connection.h"
#include "mojo/runner/child/test_native_service.mojom.h"
#include "mojo/runner/init.h"
#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h"
namespace {
class EDKState : public mojo::embedder::ProcessDelegate {
public:
EDKState() : io_thread_("io_thread") {
mojo::embedder::Init();
// Create and start our I/O thread.
base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0);
CHECK(io_thread_.StartWithOptions(io_thread_options));
io_runner_ = io_thread_.task_runner().get();
CHECK(io_runner_.get());
// TODO(vtl): This should be SLAVE, not NONE.
mojo::embedder::InitIPCSupport(mojo::embedder::ProcessType::NONE,
io_runner_, this, io_runner_,
mojo::embedder::ScopedPlatformHandle());
}
~EDKState() override { mojo::embedder::ShutdownIPCSupport(); }
private:
// mojo::embedder::ProcessDelegate:
void OnShutdownComplete() override {}
base::Thread io_thread_;
scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
DISALLOW_COPY_AND_ASSIGN(EDKState);
};
class TargetApplicationDelegate
: public mojo::ApplicationDelegate,
public mojo::runner::test::TestNativeService,
public mojo::InterfaceFactory<mojo::runner::test::TestNativeService> {
public:
TargetApplicationDelegate() {}
~TargetApplicationDelegate() override {}
private:
// mojo::ApplicationDelegate:
void Initialize(mojo::ApplicationImpl* app) override {}
bool ConfigureIncomingConnection(
mojo::ApplicationConnection* connection) override {
connection->AddService<mojo::runner::test::TestNativeService>(this);
return true;
}
// mojo::runner::test::TestNativeService:
void Invert(bool from_driver, const InvertCallback& callback) override {
callback.Run(!from_driver);
}
// mojo::InterfaceFactory<mojo::runner::test::TestNativeService>:
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<mojo::runner::test::TestNativeService>
request) override {
bindings_.AddBinding(this, request.Pass());
}
mojo::WeakBindingSet<mojo::runner::test::TestNativeService> bindings_;
DISALLOW_COPY_AND_ASSIGN(TargetApplicationDelegate);
};
} // namespace
int main(int argc, char** argv) {
base::AtExitManager at_exit;
base::CommandLine::Init(argc, argv);
mojo::runner::InitializeLogging();
mojo::runner::WaitForDebuggerIfNecessary();
#if !defined(OFFICIAL_BUILD)
base::debug::EnableInProcessStackDumping();
#if defined(OS_WIN)
base::RouteStdioToConsole(false);
#endif
#endif
{
EDKState edk;
mojo::InterfaceRequest<mojo::Application> application_request;
scoped_ptr<mojo::runner::RunnerConnection> connection(
mojo::runner::RunnerConnection::ConnectToRunner(&application_request));
TargetApplicationDelegate delegate;
{
base::MessageLoop loop(mojo::common::MessagePumpMojo::Create());
mojo::ApplicationImpl impl(&delegate, application_request.Pass());
loop.Run();
}
connection.reset();
}
return 0;
}
// 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 "mojo/runner/child/runner_connection.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "mojo/message_pump/message_pump_mojo.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/runner/child/child_controller.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"
namespace mojo {
namespace runner {
namespace {
// Blocks a thread until another thread unblocks it, at which point it unblocks
// and runs a closure provided by that thread.
class Blocker {
public:
class Unblocker {
public:
explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {}
~Unblocker() {}
void Unblock(base::Closure run_after) {
DCHECK(blocker_);
DCHECK(blocker_->run_after_.is_null());
blocker_->run_after_ = run_after;
blocker_->event_.Signal();
blocker_ = nullptr;
}
private:
Blocker* blocker_;
// Copy and assign allowed.
};
Blocker() : event_(true, false) {}
~Blocker() {}
void Block() {
DCHECK(run_after_.is_null());
event_.Wait();
if (!run_after_.is_null())
run_after_.Run();
}
Unblocker GetUnblocker() { return Unblocker(this); }
private:
base::WaitableEvent event_;
base::Closure run_after_;
DISALLOW_COPY_AND_ASSIGN(Blocker);
};
using GotApplicationRequestCallback =
base::Callback<void(InterfaceRequest<Application>)>;
void OnGotApplicationRequest(InterfaceRequest<Application>* out_request,
InterfaceRequest<Application> request) {
*out_request = request.Pass();
}
class ChildControllerImpl;
class RunnerConnectionImpl : public RunnerConnection {
public:
RunnerConnectionImpl() : controller_thread_("controller_thread") {
StartControllerThread();
}
~RunnerConnectionImpl() override {
controller_runner_->PostTask(
FROM_HERE, base::Bind(&RunnerConnectionImpl::ShutdownOnControllerThread,
base::Unretained(this)));
controller_thread_.Stop();
}
// Returns true if a connection to the runner has been established and
// |request| has been modified, false if no connection was established.
bool WaitForApplicationRequest(InterfaceRequest<Application>* request);
ChildControllerImpl* controller() const { return controller_.get(); }
void set_controller(scoped_ptr<ChildControllerImpl> controller) {
controller_ = controller.Pass();
}
private:
void StartControllerThread() {
base::Thread::Options controller_thread_options;
controller_thread_options.message_loop_type =
base::MessageLoop::TYPE_CUSTOM;
controller_thread_options.message_pump_factory =
base::Bind(&common::MessagePumpMojo::Create);
CHECK(controller_thread_.StartWithOptions(controller_thread_options));
controller_runner_ = controller_thread_.task_runner().get();
CHECK(controller_runner_.get());
}
void ShutdownOnControllerThread() { controller_.reset(); }
base::Thread controller_thread_;
scoped_refptr<base::SingleThreadTaskRunner> controller_runner_;
// Accessed only on the controller thread.
scoped_ptr<ChildControllerImpl> controller_;
DISALLOW_COPY_AND_ASSIGN(RunnerConnectionImpl);
};
class ChildControllerImpl : public ChildController {
public:
~ChildControllerImpl() override {
DCHECK(thread_checker_.CalledOnValidThread());
// TODO(vtl): Pass in the result from |MainMain()|.
on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED);
}
// To be executed on the controller thread. Creates the |ChildController|,
// etc.
static void Create(RunnerConnectionImpl* connection,
const GotApplicationRequestCallback& callback,
embedder::ScopedPlatformHandle platform_channel,
const Blocker::Unblocker& unblocker) {
DCHECK(connection);
DCHECK(platform_channel.is_valid());
DCHECK(!connection->controller());
scoped_ptr<ChildControllerImpl> impl(
new ChildControllerImpl(connection, callback, unblocker));
ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel(
platform_channel.Pass(),
base::Bind(&ChildControllerImpl::DidCreateChannel,
base::Unretained(impl.get())),
base::ThreadTaskRunnerHandle::Get()));
impl->Bind(host_message_pipe.Pass());
connection->set_controller(impl.Pass());
}
void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); }
void OnConnectionError() {
// A connection error means the connection to the shell is lost. This is not
// recoverable.
LOG(ERROR) << "Connection error to the shell.";
_exit(1);
}
// |ChildController| methods:
void StartApp(InterfaceRequest<Application> application_request,
const StartAppCallback& on_app_complete) override {
DCHECK(thread_checker_.CalledOnValidThread());
on_app_complete_ = on_app_complete;
unblocker_.Unblock(
base::Bind(&ChildControllerImpl::ReturnApplicationRequestOnMainThread,
callback_, base::Passed(&application_request)));
}
void ExitNow(int32_t exit_code) override {
DVLOG(2) << "ChildControllerImpl::ExitNow(" << exit_code << ")";
_exit(exit_code);
}
private:
ChildControllerImpl(RunnerConnectionImpl* connection,
const GotApplicationRequestCallback& callback,
const Blocker::Unblocker& unblocker)
: connection_(connection),
callback_(callback),
unblocker_(unblocker),
channel_info_(nullptr),
binding_(this) {
binding_.set_connection_error_handler([this]() { OnConnectionError(); });
}
// Callback for |embedder::CreateChannel()|.
void DidCreateChannel(embedder::ChannelInfo* channel_info) {
DVLOG(2) << "ChildControllerImpl::DidCreateChannel()";
DCHECK(thread_checker_.CalledOnValidThread());
channel_info_ = channel_info;
}
static void ReturnApplicationRequestOnMainThread(
const GotApplicationRequestCallback& callback,
InterfaceRequest<Application> application_request) {
callback.Run(application_request.Pass());
}
base::ThreadChecker thread_checker_;
RunnerConnectionImpl* const connection_;
GotApplicationRequestCallback callback_;
Blocker::Unblocker unblocker_;
StartAppCallback on_app_complete_;
embedder::ChannelInfo* channel_info_;
Binding<ChildController> binding_;
DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl);
};
bool RunnerConnectionImpl::WaitForApplicationRequest(
InterfaceRequest<Application>* request) {
embedder::ScopedPlatformHandle platform_channel =
embedder::PlatformChannelPair::PassClientHandleFromParentProcess(
*base::CommandLine::ForCurrentProcess());
if (!platform_channel.is_valid())
return false;
Blocker blocker;
controller_runner_->PostTask(
FROM_HERE,
base::Bind(
&ChildControllerImpl::Create, base::Unretained(this),
base::Bind(&OnGotApplicationRequest, base::Unretained(request)),
base::Passed(&platform_channel), blocker.GetUnblocker()));
blocker.Block();
return true;
}
} // namespace
RunnerConnection::~RunnerConnection() {}
// static
RunnerConnection* RunnerConnection::ConnectToRunner(
InterfaceRequest<Application>* request) {
RunnerConnectionImpl* connection = new RunnerConnectionImpl;
if (!connection->WaitForApplicationRequest(request)) {
delete connection;
return nullptr;
}
return connection;
}
RunnerConnection::RunnerConnection() {}
} // namespace runner
} // namespace mojo
// 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.
#ifndef MOJO_RUNNER_CHILD_RUNNER_CONNECTION_H_
#define MOJO_RUNNER_CHILD_RUNNER_CONNECTION_H_
#include "base/macros.h"
#include "mojo/application/public/interfaces/application.mojom.h"
namespace mojo {
namespace runner {
// Encapsulates a connection to a runner process. The connection object starts a
// background controller thread that is used to receive control messages from
// the runner. When this object is destroyed the thread is joined.
class RunnerConnection {
public:
virtual ~RunnerConnection();
// Establish a connection to the runner, blocking the calling thread until
// it is established. The Application request from the runner is returned via
// |request|.
// If a connection to the runner cannot be established, |request| will not be
// modified and this function will return null.
static RunnerConnection* ConnectToRunner(
InterfaceRequest<Application>* request);
protected:
RunnerConnection();
private:
DISALLOW_COPY_AND_ASSIGN(RunnerConnection);
};
} // namespace runner
} // namespace mojo
#endif // MOJO_RUNNER_CHILD_RUNNER_CONNECTION_H_
// 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.
module mojo.runner.test;
interface TestNativeService {
Invert(bool from_driver) => (bool from_target);
};
......@@ -23,7 +23,7 @@
#include "mojo/message_pump/message_pump_mojo.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/core.h"
#include "mojo/runner/child_process.mojom.h"
#include "mojo/runner/child/child_controller.mojom.h"
#include "mojo/runner/native_application_support.h"
#include "mojo/runner/switches.h"
#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
......
......@@ -103,9 +103,18 @@ void ChildProcessHost::DidStart() {
void ChildProcessHost::DoLaunch() {
const base::CommandLine* parent_command_line =
base::CommandLine::ForCurrentProcess();
base::CommandLine child_command_line(parent_command_line->GetProgram());
base::FilePath target_path = parent_command_line->GetProgram();
// |app_path_| can be empty in tests.
if (!app_path_.MatchesExtension(FILE_PATH_LITERAL(".mojo")) &&
!app_path_.empty()) {
target_path = app_path_;
}
base::CommandLine child_command_line(target_path);
child_command_line.AppendArguments(*parent_command_line, false);
child_command_line.AppendSwitchPath(switches::kChildProcess, app_path_);
if (target_path != app_path_)
child_command_line.AppendSwitchPath(switches::kChildProcess, app_path_);
if (start_sandboxed_)
child_command_line.AppendSwitch(switches::kEnableSandbox);
......
......@@ -10,7 +10,7 @@
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
#include "base/synchronization/waitable_event.h"
#include "mojo/runner/child_process.mojom.h"
#include "mojo/runner/child/child_controller.mojom.h"
#include "mojo/runner/child_process_host.h"
#include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h"
#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
......
......@@ -10,6 +10,7 @@
#include "base/thread_task_runner_handle.h"
#include "base/threading/platform_thread.h"
#include "mojo/runner/native_application_support.h"
#include "mojo/runner/out_of_process_native_runner.h"
namespace mojo {
namespace runner {
......@@ -61,7 +62,11 @@ void InProcessNativeRunner::Run() {
app_completed_callback_runner_.Reset();
}
scoped_ptr<shell::NativeRunner> InProcessNativeRunnerFactory::Create() {
scoped_ptr<shell::NativeRunner> InProcessNativeRunnerFactory::Create(
const base::FilePath& app_path) {
// Non-Mojo apps are always run in a new process.
if (!app_path.MatchesExtension(FILE_PATH_LITERAL(".mojo")))
return make_scoped_ptr(new OutOfProcessNativeRunner(context_));
return make_scoped_ptr(new InProcessNativeRunner(context_));
}
......
......@@ -52,7 +52,8 @@ class InProcessNativeRunnerFactory : public shell::NativeRunnerFactory {
explicit InProcessNativeRunnerFactory(Context* context) : context_(context) {}
~InProcessNativeRunnerFactory() override {}
scoped_ptr<shell::NativeRunner> Create() override;
scoped_ptr<shell::NativeRunner> Create(
const base::FilePath& app_path) override;
private:
Context* const context_;
......
......@@ -50,7 +50,7 @@ class TestNativeRunnerFactory : public shell::NativeRunnerFactory {
public:
explicit TestNativeRunnerFactory(TestState* state) : state_(state) {}
~TestNativeRunnerFactory() override {}
scoped_ptr<shell::NativeRunner> Create() override {
scoped_ptr<shell::NativeRunner> Create(const base::FilePath& path) override {
return scoped_ptr<shell::NativeRunner>(new TestNativeRunner(state_));
}
......
......@@ -8,7 +8,6 @@
#include "base/callback_helpers.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "mojo/runner/child_process.mojom.h"
#include "mojo/runner/child_process_host.h"
#include "mojo/runner/in_process_native_runner.h"
......@@ -56,7 +55,8 @@ void OutOfProcessNativeRunner::AppCompleted(int32_t result) {
app_completed_callback.Run();
}
scoped_ptr<shell::NativeRunner> OutOfProcessNativeRunnerFactory::Create() {
scoped_ptr<shell::NativeRunner> OutOfProcessNativeRunnerFactory::Create(
const base::FilePath& app_path) {
return make_scoped_ptr(new OutOfProcessNativeRunner(context_));
}
......
......@@ -50,7 +50,8 @@ class OutOfProcessNativeRunnerFactory : public shell::NativeRunnerFactory {
: context_(context) {}
~OutOfProcessNativeRunnerFactory() override {}
scoped_ptr<shell::NativeRunner> Create() override;
scoped_ptr<shell::NativeRunner> Create(
const base::FilePath& app_path) override;
private:
Context* const context_;
......
......@@ -220,7 +220,7 @@ void ApplicationManager::RunNativeApplication(
TRACE_EVENT1("mojo_shell", "ApplicationManager::RunNativeApplication", "path",
path.AsUTF8Unsafe());
NativeRunner* runner = native_runner_factory_->Create().release();
NativeRunner* runner = native_runner_factory_->Create(path).release();
native_runners_.push_back(runner);
runner->Start(path, start_sandboxed, application_request.Pass(),
base::Bind(&ApplicationManager::CleanupRunner,
......
......@@ -43,7 +43,7 @@ class NativeRunner {
class NativeRunnerFactory {
public:
virtual ~NativeRunnerFactory() {}
virtual scoped_ptr<NativeRunner> Create() = 0;
virtual scoped_ptr<NativeRunner> Create(const base::FilePath& app_path) = 0;
};
} // namespace shell
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment