blob: 6cbb0b432a598b6a69d795237d55d27857bad2ed [file] [log] [blame]
// Copyright 2018 The Fuchsia 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 "src/ui/tools/present_view/present_view.h"
#include <lib/fidl/cpp/vector.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/strings/substitute.h"
namespace {
// The component manifest of the component that provides an implementation of
// fuchsia.intl.PropertyProvider. present_view will start it up if the flag
// --locale=... is specified.
constexpr char kIntlPropertyProviderManifest[] =
"fuchsia-pkg://fuchsia.com/intl_property_manager#meta/intl_property_manager.cmx";
} // namespace
namespace present_view {
PresentView::PresentView(std::unique_ptr<sys::ComponentContext> context)
: context_(std::move(context)) {}
bool PresentView::Present(ViewInfo view_info, fit::function<void(zx_status_t)> on_view_error) {
if (view_info.url.empty()) {
FX_LOGS(ERROR) << "present_view requires the url of a view provider application "
"to present_view.";
return false;
}
fuchsia::sys::LauncherPtr launcher = context_->svc()->Connect<fuchsia::sys::Launcher>();
// Configure the information to launch the component with.
fuchsia::sys::LaunchInfo launch_info;
std::shared_ptr<sys::ServiceDirectory> services =
sys::ServiceDirectory::CreateWithRequest(&launch_info.directory_request);
launch_info.url = std::move(view_info.url);
launch_info.arguments = fidl::VectorPtr(std::move(view_info.arguments));
zx::channel server_side, client_side;
if (!view_info.locale.empty()) {
// If we wanted present_view to serve |fuchsia.intl.ProfileProvider|, then start the
// |intl_property_provider| and make it available to the component under test.
//
FX_CHECK(ZX_OK == zx::channel::create(0, &server_side, &client_side));
RunIntlService(view_info.locale, std::move(server_side), &launcher);
fuchsia::sys::ServiceListPtr injected_services(new fuchsia::sys::ServiceList);
injected_services->names.push_back(fuchsia::intl::PropertyProvider::Name_);
injected_services->host_directory = std::move(client_side);
launch_info.additional_services = std::move(injected_services);
}
// Launch the component.
launcher->CreateComponent(std::move(launch_info), view_controller_.NewRequest());
view_controller_.set_error_handler(std::move(on_view_error));
// Instruct the component to create a scenic View using one of the available
// interfaces.
auto [view_token, view_holder_token] = scenic::ViewTokenPair::New();
if (!view_info.locale.empty()) {
// For now, use the presence of a locale option as an indication to use the
// |fuchsia.ui.views.View| interface.
view_ = services->Connect<fuchsia::ui::views::View>();
view_->Present(std::move(view_token));
} else {
legacy_view_provider_ = services->Connect<fuchsia::ui::app::ViewProvider>();
legacy_view_provider_->CreateView(std::move(view_token.value), nullptr, nullptr);
}
// Ask the presenter to display it.
presenter_ = context_->svc()->Connect<fuchsia::ui::policy::Presenter>();
presenter_->PresentView(std::move(view_holder_token), nullptr);
return true;
}
void PresentView::RunIntlService(const std::string& locale, zx::channel server_side,
fuchsia::sys::LauncherPtr* launcher) {
FX_LOGS(INFO) << "Starting intl property provider with locale: " << locale;
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = kIntlPropertyProviderManifest;
launch_info.arguments.emplace();
launch_info.arguments->push_back("--set_initial_profile");
launch_info.arguments->push_back(fxl::Substitute("--locale_ids=$0", locale));
launch_info.directory_request = std::move(server_side);
(*launcher)->CreateComponent(std::move(launch_info), view_controller_.NewRequest());
}
} // namespace present_view