Commit e26716b5 authored by Sergey Ulanov's avatar Sergey Ulanov Committed by Commit Bot

[Fuchsia] Add Context, Frame stubs; implement service glue.

* Add ContextImpl service.
* Add FrameImpl service.
* Add support for exiting after final disconnect to ContextProvider.
* Add Context process startup logic to main.cc.
* Rename webrunner_main.cc to web_context_service_main.cc.

Bug: 852145
Change-Id: I87228259472cc0ef1044ea3e00f94de9a0f61990
Reviewed-on: https://chromium-review.googlesource.com/1114321
Commit-Queue: Sergey Ulanov <sergeyu@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#574445}
parent e5f10ba6
...@@ -47,7 +47,7 @@ executable("runner_exe") { ...@@ -47,7 +47,7 @@ executable("runner_exe") {
group("webrunner") { group("webrunner") {
testonly = true testonly = true
deps = [ deps = [
":service_exe", ":service_pkg",
":service_unittests", ":service_unittests",
] ]
} }
...@@ -112,8 +112,12 @@ component("service_lib") { ...@@ -112,8 +112,12 @@ component("service_lib") {
"common/webrunner_content_client.cc", "common/webrunner_content_client.cc",
"common/webrunner_content_client.h", "common/webrunner_content_client.h",
"common/webrunner_export.h", "common/webrunner_export.h",
"service/context_provider/context_provider_impl.cc", "service/context_impl.cc",
"service/context_provider/context_provider_impl.h", "service/context_impl.h",
"service/context_provider_impl.cc",
"service/context_provider_impl.h",
"service/frame_impl.cc",
"service/frame_impl.h",
"service/switches.cc", "service/switches.cc",
"service/switches.h", "service/switches.h",
"service/webrunner_main_delegate.cc", "service/webrunner_main_delegate.cc",
...@@ -161,7 +165,7 @@ repack("service_pak") { ...@@ -161,7 +165,7 @@ repack("service_pak") {
test("service_unittests") { test("service_unittests") {
sources = [ sources = [
"service/context_provider/context_provider_impl_unittest.cc", "service/context_provider_impl_unittest.cc",
] ]
deps = [ deps = [
":fidl", ":fidl",
......
// 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_SERVICE_COMMON_H_
#define WEBRUNNER_SERVICE_COMMON_H_
#include <zircon/processargs.h>
namespace webrunner {
const uint32_t kContextRequestHandleId = PA_HND(PA_USER0, 0);
} // namespace webrunner
#endif // WEBRUNNER_SERVICE_COMMON_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 "webrunner/service/context_impl.h"
#include <memory>
#include <utility>
#include "webrunner/service/frame_impl.h"
namespace webrunner {
ContextImpl::ContextImpl() = default;
ContextImpl::~ContextImpl() = default;
void ContextImpl::CreateFrame(
::fidl::InterfaceHandle<chromium::web::FrameObserver> observer,
::fidl::InterfaceRequest<chromium::web::Frame> frame_request) {
std::unique_ptr<chromium::web::Frame> frame =
std::make_unique<FrameImpl>(observer.Bind());
frame_bindings_.AddBinding(std::move(frame), std::move(frame_request));
}
} // 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_SERVICE_CONTEXT_IMPL_H_
#define WEBRUNNER_SERVICE_CONTEXT_IMPL_H_
#include <lib/fidl/cpp/binding_set.h>
#include <memory>
#include "base/macros.h"
#include "chromium/web/cpp/fidl.h"
#include "webrunner/common/webrunner_export.h"
namespace webrunner {
// Implementation of Context from //webrunner/fidl/context.fidl.
// Owns a BrowserContext instance and uses it to create new WebContents/Frames.
// All created Frames are owned by this object.
class WEBRUNNER_EXPORT ContextImpl : public chromium::web::Context {
public:
ContextImpl();
// Tears down the Context, destroying any active Frames in the process.
~ContextImpl() override;
// chromium::web::Context implementation.
void CreateFrame(
::fidl::InterfaceHandle<chromium::web::FrameObserver> observer,
::fidl::InterfaceRequest<chromium::web::Frame> frame) override;
private:
fidl::BindingSet<chromium::web::Frame, std::unique_ptr<chromium::web::Frame>>
frame_bindings_;
DISALLOW_COPY_AND_ASSIGN(ContextImpl);
};
} // namespace webrunner
#endif // WEBRUNNER_SERVICE_CONTEXT_IMPL_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "webrunner/service/context_provider/context_provider_impl.h" #include "webrunner/service/context_provider_impl.h"
#include <fuchsia/sys/cpp/fidl.h> #include <fuchsia/sys/cpp/fidl.h>
#include <lib/zx/job.h> #include <lib/zx/job.h>
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "base/fuchsia/fuchsia_logging.h" #include "base/fuchsia/fuchsia_logging.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/process/launch.h" #include "base/process/launch.h"
#include "webrunner/service/common.h"
#include "webrunner/service/switches.h" #include "webrunner/service/switches.h"
namespace webrunner { namespace webrunner {
...@@ -58,7 +59,7 @@ void ContextProviderImpl::Create( ...@@ -58,7 +59,7 @@ void ContextProviderImpl::Create(
base::LaunchOptions launch_options; base::LaunchOptions launch_options;
zx::channel context_handle(context_request.TakeChannel()); zx::channel context_handle(context_request.TakeChannel());
launch_options.handles_to_transfer.push_back( launch_options.handles_to_transfer.push_back(
{PA_HND(PA_USER0, 0), context_handle.get()}); {kContextRequestHandleId, context_handle.get()});
// Isolate the child Context processes by containing them within their own // Isolate the child Context processes by containing them within their own
// respective jobs. // respective jobs.
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef WEBRUNNER_SERVICE_CONTEXT_PROVIDER_CONTEXT_PROVIDER_IMPL_H_ #ifndef WEBRUNNER_SERVICE_CONTEXT_PROVIDER_IMPL_H_
#define WEBRUNNER_SERVICE_CONTEXT_PROVIDER_CONTEXT_PROVIDER_IMPL_H_ #define WEBRUNNER_SERVICE_CONTEXT_PROVIDER_IMPL_H_
#include <lib/fidl/cpp/binding_set.h> #include <lib/fidl/cpp/binding_set.h>
...@@ -55,4 +55,4 @@ class WEBRUNNER_EXPORT ContextProviderImpl ...@@ -55,4 +55,4 @@ class WEBRUNNER_EXPORT ContextProviderImpl
} // namespace webrunner } // namespace webrunner
#endif // WEBRUNNER_SERVICE_CONTEXT_PROVIDER_CONTEXT_PROVIDER_IMPL_H_ #endif // WEBRUNNER_SERVICE_CONTEXT_PROVIDER_IMPL_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "webrunner/service/context_provider/context_provider_impl.h" #include "webrunner/service/context_provider_impl.h"
#include <lib/fidl/cpp/binding.h> #include <lib/fidl/cpp/binding.h>
#include <zircon/processargs.h> #include <zircon/processargs.h>
...@@ -12,31 +12,42 @@ ...@@ -12,31 +12,42 @@
#include "base/base_switches.h" #include "base/base_switches.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/files/file.h" #include "base/files/file.h"
#include "base/fuchsia/file_utils.h" #include "base/fuchsia/file_utils.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/test/multiprocess_test.h" #include "base/test/multiprocess_test.h"
#include "testing/gmock/include/gmock/gmock-actions.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h" #include "testing/multiprocess_func_list.h"
#include "webrunner/service/common.h"
namespace webrunner { namespace webrunner {
namespace { namespace {
class MockFrameObserver : public chromium::web::FrameObserver { class TestFrameObserver : public chromium::web::FrameObserver {
public: public:
void OnNavigationStateChanged( void OnNavigationStateChanged(
chromium::web::NavigationStateChangeDetails change, chromium::web::NavigationStateChangeDetails change,
OnNavigationStateChangedCallback callback) override { OnNavigationStateChangedCallback callback) override {
OnNavigationStateChanged(); last_change_ = change;
if (change_callback_)
std::move(change_callback_).Run();
callback();
} }
MOCK_METHOD0(OnNavigationStateChanged, void(void)); void SetNextChangeCallback(base::OnceClosure callback) {
}; change_callback_ = std::move(callback);
}
chromium::web::NavigationStateChangeDetails last_change() {
return last_change_;
}
void DoNothing() {} private:
chromium::web::NavigationStateChangeDetails last_change_ = {};
base::OnceClosure change_callback_;
};
class FakeContext : public chromium::web::Context { class FakeContext : public chromium::web::Context {
public: public:
...@@ -44,22 +55,27 @@ class FakeContext : public chromium::web::Context { ...@@ -44,22 +55,27 @@ class FakeContext : public chromium::web::Context {
::fidl::InterfaceHandle<chromium::web::FrameObserver> observer, ::fidl::InterfaceHandle<chromium::web::FrameObserver> observer,
::fidl::InterfaceRequest<chromium::web::Frame> frame) override { ::fidl::InterfaceRequest<chromium::web::Frame> frame) override {
chromium::web::NavigationStateChangeDetails details; chromium::web::NavigationStateChangeDetails details;
details.url_changed = true;
details.entry.url = ""; details.entry.url = "";
details.entry.title = ""; details.entry.title = "";
observer.Bind()->OnNavigationStateChanged(details, &DoNothing); observer.Bind()->OnNavigationStateChanged(details, []() {});
} }
}; };
MULTIPROCESS_TEST_MAIN(SpawnContextServer) { MULTIPROCESS_TEST_MAIN(SpawnContextServer) {
base::MessageLoopForIO message_loop; base::MessageLoopForIO message_loop;
FakeContext fake_context; FakeContext fake_context;
zx_handle_t context_handle = zx_take_startup_handle(PA_HND(PA_USER0, 0)); zx::channel context_handle{zx_take_startup_handle(kContextRequestHandleId)};
CHECK_NE(ZX_HANDLE_INVALID, context_handle); CHECK(context_handle);
fidl::Binding<chromium::web::Context> binding(&fake_context, fidl::Binding<chromium::web::Context> binding(&fake_context,
zx::channel(context_handle)); std::move(context_handle));
// Service the MessageLoop until the child process is torn down. base::RunLoop run_loop;
base::RunLoop().Run();
// Quit the process when the context is destroyed.
binding.set_error_handler([&run_loop]() { run_loop.Quit(); });
run_loop.Run();
return 0; return 0;
} }
...@@ -72,12 +88,10 @@ class ContextProviderImplTest : public base::MultiProcessTest { ...@@ -72,12 +88,10 @@ class ContextProviderImplTest : public base::MultiProcessTest {
&ContextProviderImplTest::LaunchProcess, base::Unretained(this))); &ContextProviderImplTest::LaunchProcess, base::Unretained(this)));
provider_.Bind(provider_ptr_.NewRequest()); provider_.Bind(provider_ptr_.NewRequest());
} }
~ContextProviderImplTest() override = default;
void TearDown() override { ~ContextProviderImplTest() override {
for (auto& process : context_processes_) { provider_ptr_.Unbind();
process.Terminate(0, true); base::RunLoop().RunUntilIdle();
}
} }
// Start a new child process whose main function is defined in // Start a new child process whose main function is defined in
...@@ -86,9 +100,8 @@ class ContextProviderImplTest : public base::MultiProcessTest { ...@@ -86,9 +100,8 @@ class ContextProviderImplTest : public base::MultiProcessTest {
auto cmdline = base::GetMultiProcessTestChildBaseCommandLine(); auto cmdline = base::GetMultiProcessTestChildBaseCommandLine();
cmdline.AppendSwitchASCII(switches::kTestChildProcess, cmdline.AppendSwitchASCII(switches::kTestChildProcess,
"SpawnContextServer"); "SpawnContextServer");
auto context_process = base::LaunchProcess(cmdline, options); base::Process context_process = base::LaunchProcess(cmdline, options);
EXPECT_TRUE(context_process.IsValid()); EXPECT_TRUE(context_process.IsValid());
context_processes_.push_back(context_process.Duplicate());
return context_process; return context_process;
} }
...@@ -98,59 +111,52 @@ class ContextProviderImplTest : public base::MultiProcessTest { ...@@ -98,59 +111,52 @@ class ContextProviderImplTest : public base::MultiProcessTest {
ContextProviderImpl provider_; ContextProviderImpl provider_;
chromium::web::ContextProviderPtr provider_ptr_; chromium::web::ContextProviderPtr provider_ptr_;
// The spawned Process object for a Context.
std::vector<base::Process> context_processes_;
private: private:
DISALLOW_COPY_AND_ASSIGN(ContextProviderImplTest); DISALLOW_COPY_AND_ASSIGN(ContextProviderImplTest);
}; };
TEST_F(ContextProviderImplTest, LaunchContext) { TEST_F(ContextProviderImplTest, LaunchContext) {
// Connect to a new context process. // Connect to a new context process.
auto data_dir = base::fuchsia::GetHandleFromFile(base::File(
base::FilePath("/data"), base::File::FLAG_OPEN | base::File::FLAG_READ));
fidl::InterfacePtr<chromium::web::Context> context; fidl::InterfacePtr<chromium::web::Context> context;
chromium::web::CreateContextParams create_params; chromium::web::CreateContextParams create_params;
provider_ptr_->Create(std::move(create_params), context.NewRequest()); provider_ptr_->Create(std::move(create_params), context.NewRequest());
// Call a Context method and wait for it to invoke an observer call. // Call a Context method and wait for it to invoke an observer call.
MockFrameObserver frame_observer; TestFrameObserver frame_observer;
chromium::web::FramePtr frame_ptr; chromium::web::FramePtr frame_ptr;
fidl::Binding<chromium::web::FrameObserver> frame_observer_binding( fidl::Binding<chromium::web::FrameObserver> frame_observer_binding(
&frame_observer); &frame_observer);
base::RunLoop r; base::RunLoop run_loop;
EXPECT_CALL(frame_observer, OnNavigationStateChanged()) frame_observer.SetNextChangeCallback(run_loop.QuitClosure());
.WillOnce(testing::Invoke(&r, &base::RunLoop::Quit));
context->CreateFrame(frame_observer_binding.NewBinding(), context->CreateFrame(frame_observer_binding.NewBinding(),
frame_ptr.NewRequest()); frame_ptr.NewRequest());
r.Run(); run_loop.Run();
EXPECT_TRUE(frame_observer.last_change().url_changed ||
frame_observer.last_change().title_changed);
} }
// Verify that there can be more than one connection to the provider.
TEST_F(ContextProviderImplTest, MultipleClients) { TEST_F(ContextProviderImplTest, MultipleClients) {
{ chromium::web::ContextProviderPtr provider_1_ptr;
chromium::web::ContextProviderPtr provider_2_ptr; provider_.Bind(provider_1_ptr.NewRequest());
provider_.Bind(provider_2_ptr.NewRequest());
// Allow provider_2_ptr to go out of scope and disconnect.
}
// Connect with a third client. // Connect a second client.
chromium::web::ContextProviderPtr provider_3_ptr; chromium::web::ContextProviderPtr provider_2_ptr;
provider_.Bind(provider_3_ptr.NewRequest()); provider_.Bind(provider_2_ptr.NewRequest());
fidl::InterfacePtr<chromium::web::Context> context; fidl::InterfacePtr<chromium::web::Context> context;
chromium::web::CreateContextParams create_params; chromium::web::CreateContextParams create_params;
provider_3_ptr->Create(std::move(create_params), context.NewRequest()); provider_2_ptr->Create(std::move(create_params), context.NewRequest());
MockFrameObserver frame_observer; TestFrameObserver frame_observer;
chromium::web::FramePtr frame_ptr; chromium::web::FramePtr frame_ptr;
fidl::Binding<chromium::web::FrameObserver> frame_observer_binding( fidl::Binding<chromium::web::FrameObserver> frame_observer_binding(
&frame_observer); &frame_observer);
base::RunLoop r; base::RunLoop run_loop;
EXPECT_CALL(frame_observer, OnNavigationStateChanged()) frame_observer.SetNextChangeCallback(run_loop.QuitClosure());
.WillOnce(testing::Invoke(&r, &base::RunLoop::Quit));
context->CreateFrame(frame_observer_binding.NewBinding(), context->CreateFrame(frame_observer_binding.NewBinding(),
frame_ptr.NewRequest()); frame_ptr.NewRequest());
r.Run(); run_loop.Run();
} }
} // namespace webrunner } // 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.
#include "webrunner/service/frame_impl.h"
#include "base/logging.h"
namespace webrunner {
FrameImpl::FrameImpl(chromium::web::FrameObserverPtr observer)
: observer_(std::move(observer)) {}
FrameImpl::~FrameImpl() = default;
void FrameImpl::CreateView(
::fidl::InterfaceRequest<fuchsia::ui::views_v1_token::ViewOwner> view_owner,
::fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) {
NOTIMPLEMENTED();
}
void FrameImpl::GetNavigationController(
::fidl::InterfaceRequest<chromium::web::NavigationController> controller) {
controller_bindings_.AddBinding(this, std::move(controller));
}
void FrameImpl::LoadUrl(
::fidl::StringPtr url,
::std::unique_ptr<chromium::web::LoadUrlParams> params) {
NOTIMPLEMENTED() << "Loading URL " << *url;
}
void FrameImpl::GoBack() {
NOTIMPLEMENTED();
}
void FrameImpl::GoForward() {
NOTIMPLEMENTED();
}
void FrameImpl::Stop() {
NOTIMPLEMENTED();
}
void FrameImpl::Reload() {
NOTIMPLEMENTED();
}
void FrameImpl::GetVisibleEntry(GetVisibleEntryCallback callback) {
NOTIMPLEMENTED();
callback(nullptr);
}
} // 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_SERVICE_FRAME_IMPL_H_
#define WEBRUNNER_SERVICE_FRAME_IMPL_H_
#include <lib/fidl/cpp/binding_set.h>
#include <memory>
#include <utility>
#include "base/macros.h"
#include "chromium/web/cpp/fidl.h"
namespace webrunner {
// Implementation of Frame from //webrunner/fidl/frame.fidl.
// Implements a Frame service, which is a wrapper for a WebContents instance.
class FrameImpl : public chromium::web::Frame,
public chromium::web::NavigationController {
public:
explicit FrameImpl(chromium::web::FrameObserverPtr observer);
~FrameImpl() override;
// chromium::web::Frame implementation.
void CreateView(
::fidl::InterfaceRequest<fuchsia::ui::views_v1_token::ViewOwner>
view_owner,
::fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services)
override;
void GetNavigationController(
::fidl::InterfaceRequest<chromium::web::NavigationController> controller)
override;
// chromium::web::NavigationController implementation.
void LoadUrl(::fidl::StringPtr url,
::std::unique_ptr<chromium::web::LoadUrlParams> params) override;
void GoBack() override;
void GoForward() override;
void Stop() override;
void Reload() override;
void GetVisibleEntry(GetVisibleEntryCallback callback) override;
private:
chromium::web::FrameObserverPtr observer_;
fidl::BindingSet<chromium::web::NavigationController> controller_bindings_;
DISALLOW_COPY_AND_ASSIGN(FrameImpl);
};
} // namespace webrunner
#endif // WEBRUNNER_SERVICE_FRAME_IMPL_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