blob: b29f8316208978fc84d49f44b851cf38955c505a [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 "services/ui/launcher/launcher_app.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/trace_event/trace_event.h"
#include "mojo/application/application_runner_chromium.h"
#include "mojo/common/tracing_impl.h"
#include "mojo/public/c/system/main.h"
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/application/connect.h"
#include "mojo/public/cpp/application/service_provider_impl.h"
namespace launcher {
LauncherApp::LauncherApp() : app_impl_(nullptr), next_id_(0u) {}
LauncherApp::~LauncherApp() {}
void LauncherApp::Initialize(mojo::ApplicationImpl* app_impl) {
app_impl_ = app_impl;
auto command_line = base::CommandLine::ForCurrentProcess();
command_line->InitFromArgv(app_impl_->args());
logging::LoggingSettings settings;
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
logging::InitLogging(settings);
tracing_.Initialize(app_impl_->shell(), &app_impl_->args());
TRACE_EVENT0("launcher", __func__);
InitCompositor();
InitViewManager();
InitViewAssociates(command_line->GetSwitchValueASCII("view_associate_urls"));
for (size_t i = 0; i < command_line->GetArgs().size(); ++i) {
Launch(command_line->GetArgs()[i]);
}
}
void LauncherApp::InitCompositor() {
mojo::ConnectToService(app_impl_->shell(), "mojo:compositor_service",
GetProxy(&compositor_));
compositor_.set_connection_error_handler(base::Bind(
&LauncherApp::OnCompositorConnectionError, base::Unretained(this)));
}
void LauncherApp::InitViewManager() {
mojo::ConnectToService(app_impl_->shell(), "mojo:view_manager_service",
GetProxy(&view_manager_));
view_manager_.set_connection_error_handler(base::Bind(
&LauncherApp::OnViewManagerConnectionError, base::Unretained(this)));
}
void LauncherApp::InitViewAssociates(
const std::string& associate_urls_command_line_param) {
// Build up the list of ViewAssociates we are going to start
auto associate_urls =
SplitString(associate_urls_command_line_param, ",", base::KEEP_WHITESPACE,
base::SPLIT_WANT_ALL);
// If there's nothing we got from the command line, use our own list
if (associate_urls.empty()) {
// TODO(jeffbrown): Replace this hardcoded list.
associate_urls.push_back("mojo:input_manager_service");
}
view_associate_owners_.reserve(associate_urls.size());
// Connect to ViewAssociates.
for (const auto& url : associate_urls) {
// Connect to the ViewAssociate.
DVLOG(2) << "Connecting to ViewAssociate " << url;
mojo::ui::ViewAssociatePtr view_associate;
mojo::ConnectToService(app_impl_->shell(), url, GetProxy(&view_associate));
// Wire up the associate to the ViewManager.
mojo::ui::ViewAssociateOwnerPtr view_associate_owner;
view_manager_->RegisterViewAssociate(view_associate.Pass(),
GetProxy(&view_associate_owner), url);
view_associate_owner.set_connection_error_handler(base::Bind(
&LauncherApp::OnViewAssociateConnectionError, base::Unretained(this)));
view_associate_owners_.push_back(view_associate_owner.Pass());
}
view_manager_->FinishedRegisteringViewAssociates();
}
bool LauncherApp::ConfigureIncomingConnection(
mojo::ServiceProviderImpl* service_provider_impl) {
// Only present the launcher interface to the shell.
if (service_provider_impl->connection_context().remote_url.empty()) {
service_provider_impl->AddService<Launcher>(
[this](const mojo::ConnectionContext& connection_context,
mojo::InterfaceRequest<Launcher> launcher_request) {
bindings_.AddBinding(this, launcher_request.Pass());
});
}
return true;
}
void LauncherApp::Launch(const mojo::String& application_url) {
DVLOG(1) << "Launching " << application_url;
mojo::NativeViewportPtr viewport;
mojo::ConnectToService(app_impl_->shell(), "mojo:native_viewport_service",
GetProxy(&viewport));
mojo::ui::ViewProviderPtr view_provider;
mojo::ConnectToService(app_impl_->shell(), application_url,
GetProxy(&view_provider));
LaunchInternal(viewport.Pass(), view_provider.Pass());
}
void LauncherApp::LaunchOnViewport(
mojo::InterfaceHandle<mojo::NativeViewport> viewport,
mojo::InterfaceHandle<mojo::ui::ViewProvider> view_provider) {
LaunchInternal(mojo::NativeViewportPtr::Create(viewport.Pass()),
mojo::ui::ViewProviderPtr::Create(view_provider.Pass()));
}
void LauncherApp::LaunchInternal(mojo::NativeViewportPtr viewport,
mojo::ui::ViewProviderPtr view_provider) {
uint32_t next_id = next_id_++;
std::unique_ptr<LaunchInstance> instance(new LaunchInstance(
app_impl_, viewport.Pass(), view_provider.Pass(), compositor_.get(),
view_manager_.get(), base::Bind(&LauncherApp::OnLaunchTermination,
base::Unretained(this), next_id)));
instance->Launch();
launch_instances_.emplace(next_id, std::move(instance));
}
void LauncherApp::OnLaunchTermination(uint32_t id) {
launch_instances_.erase(id);
if (launch_instances_.empty()) {
app_impl_->Terminate();
}
}
void LauncherApp::OnCompositorConnectionError() {
LOG(ERROR) << "Exiting due to compositor connection error.";
app_impl_->Terminate();
}
void LauncherApp::OnViewManagerConnectionError() {
LOG(ERROR) << "Exiting due to view manager connection error.";
app_impl_->Terminate();
}
void LauncherApp::OnViewAssociateConnectionError() {
LOG(ERROR) << "Exiting due to view associate connection error.";
app_impl_->Terminate();
};
} // namespace launcher