blob: a4d0b8a9352ea3fd03bc751d65d11d57c3e8d4db [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 "base/at_exit.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/simple_platform_support.h"
#include "shell/external_application_registrar_connection.h"
#include "shell/in_process_dynamic_service_runner.h"
#include "shell/init.h"
#include "url/gurl.h"
namespace {
const char kAppPath[] = "app-path";
const char kAppURL[] = "app-url";
const char kShellPath[] = "shell-path";
}
class Launcher {
public:
explicit Launcher(base::CommandLine* command_line)
: app_path_(command_line->GetSwitchValuePath(kAppPath)),
app_url_(command_line->GetSwitchValueASCII(kAppURL)),
loop_(base::MessageLoop::TYPE_IO),
connection_(
base::FilePath(command_line->GetSwitchValuePath(kShellPath))),
connect_result_(0) {}
~Launcher() {}
int Connect() {
DCHECK(!run_loop_.get());
run_loop_.reset(new base::RunLoop);
connection_.Connect(
base::Bind(&Launcher::OnConnected, base::Unretained(this)));
run_loop_->Run();
run_loop_.reset();
return connect_result_;
}
bool Register() {
DCHECK(!run_loop_.get());
DCHECK(connect_result_ == 0);
run_loop_.reset(new base::RunLoop);
connection_.Register(
app_url_, base::Bind(&Launcher::OnRegistered, base::Unretained(this)));
run_loop_->Run();
run_loop_.reset();
return shell_handle_.is_valid();
}
void Run() {
DCHECK(!run_loop_.get());
DCHECK(shell_handle_.is_valid());
mojo::shell::InProcessDynamicServiceRunner service_runner(nullptr);
run_loop_.reset(new base::RunLoop);
service_runner.Start(
app_path_, shell_handle_.Pass(),
base::Bind(&Launcher::OnAppCompleted, base::Unretained(this)));
run_loop_->Run();
run_loop_.reset();
}
private:
void OnConnected(int result) {
connect_result_ = result;
run_loop_->Quit();
}
void OnRegistered(mojo::ShellPtr shell) {
shell_handle_ = shell.PassMessagePipe();
run_loop_->Quit();
}
void OnAppCompleted() { run_loop_->Quit(); }
const base::FilePath app_path_;
const GURL app_url_;
base::MessageLoop loop_;
mojo::shell::ExternalApplicationRegistrarConnection connection_;
int connect_result_;
mojo::ScopedMessagePipeHandle shell_handle_;
scoped_ptr<base::RunLoop> run_loop_;
};
#if defined(OS_WIN)
int main(int argc, wchar_t** argv) {
#else
int main(int argc, char** argv) {
#endif
base::AtExitManager at_exit;
mojo::embedder::Init(scoped_ptr<mojo::embedder::PlatformSupport>(
new mojo::embedder::SimplePlatformSupport()));
base::CommandLine::Init(argc, argv);
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
mojo::shell::InitializeLogging();
Launcher launcher(command_line);
int result = launcher.Connect();
if (result < 0) {
LOG(ERROR) << "Error(" << result << ") connecting on socket "
<< command_line->GetSwitchValueASCII(kShellPath);
return MOJO_RESULT_INVALID_ARGUMENT;
}
if (!launcher.Register()) {
LOG(ERROR) << "Error registering "
<< command_line->GetSwitchValueASCII(kAppURL);
return MOJO_RESULT_INVALID_ARGUMENT;
}
launcher.Run();
return MOJO_RESULT_OK;
}