Commit 4d2d4522 authored by Sergey Ulanov's avatar Sergey Ulanov Committed by Commit Bot

[Fuchsia] Implement WebRunner as a sys::Runner service.

* Add RunnerImpl for servicing Runner FIDL requests.
* Add ComponentController class for managing the lifetime of connected
  Runner clients, and servicing ViewProvider::CreateView() calls.
* Add "runner" package, deployment scripts, etc.
* Modify ScopedServiceBinding to support multiple clients.

Bug: 856416
Change-Id: I1b3fd00e868f5eed6842f711986a13c0296a4c07
Reviewed-on: https://chromium-review.googlesource.com/1114377Reviewed-by: default avatarWez <wez@chromium.org>
Commit-Queue: Sergey Ulanov <sergeyu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#573996}
parent e2ce0798
...@@ -13,31 +13,59 @@ config("webrunner_implementation") { ...@@ -13,31 +13,59 @@ config("webrunner_implementation") {
defines = [ "WEBRUNNER_IMPLEMENTATION" ] defines = [ "WEBRUNNER_IMPLEMENTATION" ]
} }
fuchsia_package("runner_pkg") {
binary = ":runner_exe"
package_name_override = "web_runner"
}
fuchsia_package_runner("runner") {
package = ":runner_pkg"
package_name_override = "web_runner"
package_deps = [ [
":service_pkg",
"chromium",
] ]
}
executable("runner_exe") {
sources = [
"app/component_controller_impl.cc",
"app/component_controller_impl.h",
"app/main.cc",
"app/web_content_runner.cc",
"app/web_content_runner.h",
]
deps = [
":fidl",
"//base",
"//url",
]
}
# Uber-target, used by buildbots and :gn_all for discovery of all buildable # Uber-target, used by buildbots and :gn_all for discovery of all buildable
# webrunner code. # webrunner code.
group("webrunner") { group("webrunner") {
testonly = true testonly = true
deps = [ deps = [
":service_exec", ":service_exe",
":service_unittests", ":service_unittests",
] ]
} }
fuchsia_package("service_pkg") { fuchsia_package("service_pkg") {
binary = ":service_exec" binary = ":service_exe"
package_name_override = "chromium" package_name_override = "chromium"
} }
executable("service_exec") { executable("service_exe") {
deps = [ deps = [
":fidl", ":fidl",
":service_lib", ":service_lib",
"//base", "//base",
"//content/public/app:both", "//content/public/app:both",
] ]
sources = [ sources = [
"service/webrunner_main.cc", "service/web_content_service_main.cc",
] ]
} }
......
// 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/component_controller_impl.h"
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fidl/cpp/binding_set.h>
#include <utility>
#include <vector>
#include "base/fuchsia/scoped_service_binding.h"
#include "base/fuchsia/service_directory.h"
#include "base/logging.h"
#include "webrunner/app/web_content_runner.h"
#include "webrunner/fidl/chromium/web/cpp/fidl.h"
namespace webrunner {
ComponentControllerImpl::ComponentControllerImpl(
WebContentRunner* runner,
fuchsia::sys::Package package,
fuchsia::sys::StartupInfo startup_info,
::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
controller_request)
: runner_(runner),
controller_binding_(this),
frame_observer_binding_(this) {
DCHECK(runner);
BindToRequest(std::move(package), std::move(startup_info),
std::move(controller_request));
}
ComponentControllerImpl::~ComponentControllerImpl() {
for (WaitCallback& next_callback : termination_wait_callbacks_) {
next_callback(did_terminate_abnormally_ ? 1 : 0);
}
}
void ComponentControllerImpl::BindToRequest(
fuchsia::sys::Package package,
fuchsia::sys::StartupInfo startup_info,
::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
controller_request) {
DCHECK(!service_directory_);
DCHECK(!view_provider_binding_);
url_ = GURL(*package.resolved_url);
if (!url_.is_valid()) {
LOG(ERROR) << "Rejected invalid URL: " << url_;
// By now |this| has been destroyed by WebContentRunner, so return
// immediately.
return;
}
if (controller_request.is_valid()) {
controller_binding_.Bind(std::move(controller_request));
controller_binding_.set_error_handler(
fit::bind_member(this, &ComponentControllerImpl::Kill));
}
runner_->context()->CreateFrame(frame_observer_binding_.NewBinding(),
frame_.NewRequest());
frame_->GetNavigationController(navigation_controller_.NewRequest());
navigation_controller_->LoadUrl(url_.spec(), nullptr);
// Publish a ViewProvider service.
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::views_v1::ViewProvider>>(
service_directory_.get(), this);
}
void ComponentControllerImpl::Kill() {
did_terminate_abnormally_ = true;
runner_->DestroyComponent(this);
}
void ComponentControllerImpl::Detach() {
controller_binding_.set_error_handler(nullptr);
}
void ComponentControllerImpl::Wait(WaitCallback callback) {
termination_wait_callbacks_.push_back(std::move(callback));
}
void ComponentControllerImpl::OnNavigationStateChanged(
chromium::web::NavigationStateChangeDetails change,
OnNavigationStateChangedCallback callback) {}
void ComponentControllerImpl::CreateView(
::fidl::InterfaceRequest<fuchsia::ui::views_v1_token::ViewOwner> view_owner,
::fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) {
DCHECK(frame_);
DCHECK(!view_bound_);
frame_->CreateView(std::move(view_owner), std::move(services));
view_bound_ = true;
}
} // namespace webrunner
// 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.
#ifndef WEBRUNNER_APP_COMPONENT_CONTROLLER_IMPL_H_
#define WEBRUNNER_APP_COMPONENT_CONTROLLER_IMPL_H_
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fidl/cpp/binding_set.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/fuchsia/scoped_service_binding.h"
#include "base/fuchsia/service_directory.h"
#include "base/logging.h"
#include "url/gurl.h"
#include "webrunner/fidl/chromium/web/cpp/fidl.h"
namespace webrunner {
class WebContentRunner;
// Manages the resources and service bindings for a Runner Component creation
// request. Each ComponentControllerImpl instance manages its own
// chromium::web::Frame.
class ComponentControllerImpl : public fuchsia::sys::ComponentController,
public chromium::web::FrameObserver,
public fuchsia::ui::views_v1::ViewProvider {
public:
ComponentControllerImpl(
WebContentRunner* runner,
fuchsia::sys::Package package,
fuchsia::sys::StartupInfo startup_info,
::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
controller_request);
~ComponentControllerImpl() override;
// fuchsia::sys::ComponentController implementation.
void Kill() override;
void Detach() override;
void Wait(WaitCallback callback) override;
// chromium::web::FrameObserver implementation.
void OnNavigationStateChanged(
chromium::web::NavigationStateChangeDetails change,
OnNavigationStateChangedCallback callback) override;
// fuchsia::ui::views_v1::ViewProvider implementation.
void CreateView(
::fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
view_owner,
::fidl::InterfaceRequest<::fuchsia::sys::ServiceProvider> services)
override;
private:
friend class WebContentRunner;
// Binds |this| to a Runner::StartComponent() call.
void BindToRequest(fuchsia::sys::Package package,
fuchsia::sys::StartupInfo startup_info,
::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
controller_request);
GURL url_;
WebContentRunner* runner_ = nullptr;
// WebContextService client objects.
chromium::web::FramePtr frame_;
chromium::web::NavigationControllerPtr navigation_controller_;
// Bindings for services passed in to WebContextService.
fidl::Binding<fuchsia::sys::ComponentController> controller_binding_;
fidl::Binding<chromium::web::FrameObserver> frame_observer_binding_;
// Objects used for binding and exporting the ViewProvider service.
std::unique_ptr<base::fuchsia::ServiceDirectory> service_directory_;
std::unique_ptr<
base::fuchsia::ScopedServiceBinding<fuchsia::ui::views_v1::ViewProvider>>
view_provider_binding_;
std::vector<WaitCallback> termination_wait_callbacks_;
bool did_terminate_abnormally_ = false;
bool view_bound_ = false;
DISALLOW_COPY_AND_ASSIGN(ComponentControllerImpl);
};
} // namespace webrunner
#endif // WEBRUNNER_APP_COMPONENT_CONTROLLER_IMPL_H_
// 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 <fuchsia/ui/views_v1/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <utility>
#include "base/fuchsia/component_context.h"
#include "base/fuchsia/scoped_service_binding.h"
#include "base/fuchsia/service_directory.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "webrunner/app/web_content_runner.h"
#include "webrunner/fidl/chromium/web/cpp/fidl.h"
namespace {
chromium::web::ContextPtr CreateContext() {
auto web_context_provider =
base::fuchsia::ComponentContext::GetDefault()
->ConnectToService<chromium::web::ContextProvider>();
chromium::web::CreateContextParams create_params;
chromium::web::ContextPtr web_context;
web_context_provider->Create(std::move(create_params),
web_context.NewRequest());
web_context.set_error_handler([]() {
// If the browser instance died, then exit everything and do not attempt
// to recover. appmgr will relaunch the runner when it is needed again.
LOG(ERROR) << "Connection to Context lost.";
exit(1);
});
return web_context;
}
} // namespace
int main(int argc, char** argv) {
base::MessageLoopForIO message_loop;
auto web_context = CreateContext();
base::RunLoop run_loop;
webrunner::WebContentRunner runner(std::move(web_context),
run_loop.QuitClosure());
base::fuchsia::ServiceDirectory* directory =
base::fuchsia::ServiceDirectory::GetDefault();
// Bind the Runner FIDL instance.
base::fuchsia::ScopedServiceBinding<fuchsia::sys::Runner> runner_binding(
directory, &runner);
// The RunLoop runs until all Components have been closed, at which point the
// application will terminate.
run_loop.Run();
return 0;
}
// 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/web_content_runner.h"
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fidl/cpp/binding_set.h>
#include <utility>
#include "base/fuchsia/scoped_service_binding.h"
#include "base/fuchsia/service_directory.h"
#include "base/logging.h"
#include "webrunner/app/component_controller_impl.h"
#include "webrunner/fidl/chromium/web/cpp/fidl.h"
namespace webrunner {
WebContentRunner::WebContentRunner(chromium::web::ContextPtr context,
base::OnceClosure on_all_closed)
: context_(std::move(context)), on_all_closed_(std::move(on_all_closed)) {
DCHECK(context_);
DCHECK(on_all_closed_);
}
WebContentRunner::~WebContentRunner() = default;
void WebContentRunner::StartComponent(
fuchsia::sys::Package package,
fuchsia::sys::StartupInfo startup_info,
::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
controller_request) {
DCHECK(on_all_closed_)
<< "StartComponent() called after Runner was deactivated.";
auto controller = std::make_unique<ComponentControllerImpl>(
this, std::move(package), std::move(startup_info),
std::move(controller_request));
controller->BindToRequest(std::move(package), std::move(startup_info),
std::move(controller_request));
controllers_.insert(std::move(controller));
}
void WebContentRunner::DestroyComponent(ComponentControllerImpl* component) {
DCHECK(on_all_closed_);
controllers_.erase(controllers_.find(component));
if (controllers_.empty()) {
std::move(on_all_closed_).Run();
}
}
} // namespace webrunner
// 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.
#ifndef WEBRUNNER_APP_WEB_CONTENT_RUNNER_H_
#define WEBRUNNER_APP_WEB_CONTENT_RUNNER_H_
#include <fuchsia/sys/cpp/fidl.h>
#include <memory>
#include <set>
#include "base/callback.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/macros.h"
#include "webrunner/fidl/chromium/web/cpp/fidl.h"
namespace webrunner {
class ComponentControllerImpl;
// An implementation of a sys::Runner that launches web content and renders it
// inside a View.
class WebContentRunner : public fuchsia::sys::Runner {
public:
// |context|: The web Context used to creates Frames.
// |on_all_closed|: A closure which is invoked when the last connected Frame
// disconnects, signaling to the parent that the Context can be safely
// destroyed.
WebContentRunner(chromium::web::ContextPtr context,
base::OnceClosure on_all_closed);
~WebContentRunner() override;
chromium::web::Context* context() { return context_.get(); }
// Used by ComponentControllerImpls to signal that the controller's connection
// was dropped, and therefore the controller should be destroyed.
void DestroyComponent(ComponentControllerImpl* component);
// fuchsia::sys::Runner implementation.
void StartComponent(
fuchsia::sys::Package package,
fuchsia::sys::StartupInfo startup_info,
::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
controller_request) override;
private:
chromium::web::ContextPtr context_;
std::set<std::unique_ptr<ComponentControllerImpl>, base::UniquePtrComparator>
controllers_;
base::OnceClosure on_all_closed_;
DISALLOW_COPY_AND_ASSIGN(WebContentRunner);
};
} // namespace webrunner
#endif // WEBRUNNER_APP_WEB_CONTENT_RUNNER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment