| // 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 |