| // Copyright 2018 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 "webrunner/app/common/web_component.h" |
| |
| #include <fuchsia/sys/cpp/fidl.h> |
| #include <lib/fidl/cpp/binding_set.h> |
| #include <lib/fit/function.h> |
| #include <utility> |
| |
| #include "base/fuchsia/scoped_service_binding.h" |
| #include "base/fuchsia/service_directory.h" |
| #include "base/logging.h" |
| #include "webrunner/app/common/web_content_runner.h" |
| #include "webrunner/fidl/chromium/web/cpp/fidl.h" |
| |
| namespace webrunner { |
| |
| WebComponent::~WebComponent() { |
| // Send process termination details to the client. |
| controller_binding_.events().OnTerminated(termination_exit_code_, |
| termination_reason_); |
| } |
| |
| // static |
| std::unique_ptr<WebComponent> WebComponent::ForUrlRequest( |
| WebContentRunner* runner, |
| const GURL& url, |
| fuchsia::sys::StartupInfo startup_info, |
| fidl::InterfaceRequest<fuchsia::sys::ComponentController> |
| controller_request) { |
| DCHECK(url.is_valid()); |
| std::unique_ptr<WebComponent> component(new WebComponent( |
| runner, std::move(startup_info), std::move(controller_request))); |
| component->navigation_controller()->LoadUrl(url.spec(), nullptr); |
| return component; |
| } |
| |
| WebComponent::WebComponent( |
| WebContentRunner* runner, |
| fuchsia::sys::StartupInfo startup_info, |
| fidl::InterfaceRequest<fuchsia::sys::ComponentController> |
| controller_request) |
| : runner_(runner), controller_binding_(this) { |
| DCHECK(runner); |
| |
| // If the ComponentController request is valid then bind it, and configure it |
| // to destroy this component on error. |
| if (controller_request.is_valid()) { |
| controller_binding_.Bind(std::move(controller_request)); |
| controller_binding_.set_error_handler([this] { |
| // Signal graceful process termination. |
| DestroyComponent(0, fuchsia::sys::TerminationReason::EXITED); |
| }); |
| } |
| |
| // Create the underlying Frame and get its NavigationController. |
| runner_->context()->CreateFrame(frame_.NewRequest()); |
| frame_->GetNavigationController(navigation_controller_.NewRequest()); |
| |
| // Create a ServiceDirectory for this component, and publish a ViewProvider |
| // into it, for the caller to use to create a View for this component. |
| // Note that we must publish ViewProvider before returning control to the |
| // message-loop, to ensure that it is available before the ServiceDirectory |
| // starts processing requests. |
| service_directory_ = std::make_unique<base::fuchsia::ServiceDirectory>( |
| std::move(startup_info.launch_info.directory_request)); |
| view_provider_binding_ = std::make_unique< |
| base::fuchsia::ScopedServiceBinding<fuchsia::ui::viewsv1::ViewProvider>>( |
| service_directory_.get(), this); |
| } |
| |
| void WebComponent::Kill() { |
| // Signal abnormal process termination. |
| DestroyComponent(1, fuchsia::sys::TerminationReason::RUNNER_TERMINATED); |
| } |
| |
| void WebComponent::Detach() { |
| controller_binding_.set_error_handler(nullptr); |
| } |
| |
| void WebComponent::CreateView( |
| fidl::InterfaceRequest<fuchsia::ui::viewsv1token::ViewOwner> view_owner, |
| fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) { |
| DCHECK(frame_); |
| DCHECK(!view_is_bound_); |
| |
| frame_->CreateView(std::move(view_owner), std::move(services)); |
| view_is_bound_ = true; |
| } |
| |
| void WebComponent::DestroyComponent(int termination_exit_code, |
| fuchsia::sys::TerminationReason reason) { |
| termination_reason_ = reason; |
| termination_exit_code_ = termination_exit_code; |
| runner_->DestroyComponent(this); |
| } |
| |
| } // namespace webrunner |