// Copyright 2016 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 "flutter/content_handler/application_controller_impl.h" #include #include #include #include "flutter/content_handler/app.h" #include "flutter/content_handler/runtime_holder.h" #include "lib/app/cpp/connect.h" #include "lib/fsl/vmo/vector.h" #include "lib/fxl/logging.h" namespace flutter_runner { ApplicationControllerImpl::ApplicationControllerImpl( App* app, app::ApplicationPackagePtr application, app::ApplicationStartupInfoPtr startup_info, fidl::InterfaceRequest controller) : app_(app), binding_(this) { if (controller.is_pending()) { binding_.Bind(std::move(controller)); binding_.set_connection_error_handler([this] { app_->Destroy(this); // |this| has been deleted at this point. }); } std::vector bundle; if (!fsl::VectorFromVmo(std::move(application->data), &bundle)) { FXL_LOG(ERROR) << "Failed to receive bundle."; return; } // TODO(jeffbrown): Decide what to do with command-line arguments and // startup handles. if (startup_info->launch_info->services) { service_provider_bridge_.AddBinding( std::move(startup_info->launch_info->services)); } if (startup_info->launch_info->service_request.is_valid()) { service_provider_bridge_.ServeDirectory( std::move(startup_info->launch_info->service_request)); } service_provider_bridge_.AddService( [this](fidl::InterfaceRequest request) { view_provider_bindings_.AddBinding(this, std::move(request)); }); app::ServiceProviderPtr service_provider; auto request = service_provider.NewRequest(); service_provider_bridge_.set_backend(std::move(service_provider)); mxio_ns_t* mxio_ns = SetupNamespace(startup_info->flat_namespace); if (mxio_ns == nullptr) { FXL_LOG(ERROR) << "Failed to initialize namespace"; } url_ = startup_info->launch_info->url; runtime_holder_.reset(new RuntimeHolder()); runtime_holder_->Init( mxio_ns, app::ApplicationContext::CreateFrom(std::move(startup_info)), std::move(request), std::move(bundle)); } ApplicationControllerImpl::~ApplicationControllerImpl() = default; constexpr char kServiceRootPath[] = "/svc"; mxio_ns_t* ApplicationControllerImpl::SetupNamespace( const app::FlatNamespacePtr& flat) { mxio_ns_t* mxio_namespc; mx_status_t status = mxio_ns_create(&mxio_namespc); if (status != MX_OK) { FXL_LOG(ERROR) << "Failed to create namespace"; return nullptr; } for (size_t i = 0; i < flat->paths.size(); ++i) { if (flat->paths[i] == kServiceRootPath) { // Ownership of /svc goes to the ApplicationContext created above. continue; } mx::channel dir = std::move(flat->directories[i]); mx_handle_t dir_handle = dir.release(); const char* path = flat->paths[i].data(); status = mxio_ns_bind(mxio_namespc, path, dir_handle); if (status != MX_OK) { FXL_LOG(ERROR) << "Failed to bind " << flat->paths[i] << " to namespace"; mx_handle_close(dir_handle); mxio_ns_destroy(mxio_namespc); return nullptr; } } return mxio_namespc; } void ApplicationControllerImpl::Kill() { SendReturnCode(runtime_holder_->return_code()); runtime_holder_.reset(); app_->Destroy(this); // |this| has been deleted at this point. } void ApplicationControllerImpl::Detach() { binding_.set_connection_error_handler(fxl::Closure()); } void ApplicationControllerImpl::Wait(const WaitCallback& callback) { wait_callbacks_.push_back(callback); } void ApplicationControllerImpl::SendReturnCode(int32_t return_code) { for (const auto& iter : wait_callbacks_) { iter(return_code); } wait_callbacks_.clear(); } void ApplicationControllerImpl::CreateView( fidl::InterfaceRequest view_owner_request, fidl::InterfaceRequest services) { runtime_holder_->CreateView(url_, std::move(view_owner_request), std::move(services)); } Dart_Port ApplicationControllerImpl::GetUIIsolateMainPort() { if (!runtime_holder_) return ILLEGAL_PORT; return runtime_holder_->GetUIIsolateMainPort(); } std::string ApplicationControllerImpl::GetUIIsolateName() { if (!runtime_holder_) { return ""; } return runtime_holder_->GetUIIsolateName(); } } // namespace flutter_runner