| // 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/lib/ui/base_view/view_provider_component.h" |
| |
| #include <lib/syslog/cpp/macros.h> |
| #include <lib/ui/scenic/cpp/view_token_pair.h> |
| |
| using fuchsia::ui::views::ViewToken; |
| |
| namespace scenic { |
| |
| ViewProviderComponent::ViewProviderComponent(ViewFactory factory, async::Loop* loop, |
| sys::ComponentContext* component_context) |
| : component_context_(component_context |
| ? std::unique_ptr<sys::ComponentContext>(component_context) |
| : sys::ComponentContext::CreateAndServeOutgoingDirectory()), |
| scenic_(component_context_->svc()->Connect<fuchsia::ui::scenic::Scenic>()), |
| service_(component_context_.get(), scenic_.get(), factory.share()) { |
| // Register the |View| service. |
| component_context_->outgoing()->AddPublicService<fuchsia::ui::views::View>( |
| [this, component_context = component_context_.get(), factory = std::move(factory)]( |
| fidl::InterfaceRequest<fuchsia::ui::views::View> request) mutable { |
| view_impl_ = std::make_unique<ViewImpl>(factory.share(), std::move(request), scenic_.get(), |
| component_context); |
| view_impl_->SetErrorHandler([this] { view_impl_ = nullptr; }); |
| }); |
| |
| if (component_context) { |
| // We are only responsible for cleaning up the context if we created it |
| // ourselves. In this case we are "borrowing" an existing context that was |
| // provided to us, so we shouldn't retain a unique_ptr to it. |
| component_context_.release(); |
| } |
| |
| scenic_.set_error_handler([loop](zx_status_t status) { |
| FX_LOGS(INFO) << "Lost connection to Scenic."; |
| loop->Quit(); |
| }); |
| } |
| |
| ViewProviderComponent::ViewImpl::ViewImpl(ViewFactory factory, |
| fidl::InterfaceRequest<View> view_request, |
| fuchsia::ui::scenic::Scenic* scenic, |
| sys::ComponentContext* component_context) |
| : factory_(std::move(factory)), |
| scenic_(scenic), |
| component_context_(component_context), |
| binding_(this, std::move(view_request)) {} |
| |
| void ViewProviderComponent::ViewImpl::Present(fuchsia::ui::views::ViewToken view_token) { |
| if (view_) { |
| // This should only be called once. |
| FX_LOGS(ERROR) << "Present() can only be called once"; |
| OnError(); |
| return; |
| } |
| |
| ViewContext context = { |
| .session_and_listener_request = CreateScenicSessionPtrAndListenerRequest(scenic_), |
| .view_token = std::move(view_token), |
| .component_context = component_context_, |
| }; |
| view_ = factory_(std::move(context)); |
| } |
| |
| void ViewProviderComponent::ViewImpl::SetErrorHandler(fit::closure error_handler) { |
| error_handler_ = std::move(error_handler); |
| } |
| |
| void ViewProviderComponent::ViewImpl::OnError(zx_status_t epitaph_value) { |
| binding_.Close(epitaph_value); |
| error_handler_(); |
| } |
| |
| } // namespace scenic |