Commit 6a60f012 authored by Kevin Marshall's avatar Kevin Marshall Committed by Commit Bot

[fuchsia] Implement browser tests for WebRunner Context service.

Tests may interact with the WebRunner FIDL services and the underlying
browser objects for end to end testing of service and browser
functionality.

* Add a browser test launcher main() for WebRunner.
* Add some simple navigation tests.
* Wire up GoBack()/GoForward() FIDL calls.
* Add embedded test server resources and initialization logic.
* Add missing deletion & notification calls to BrowserContext dtor.
* Use FIDL events for navigation state changes.

* Bug fixes:
  ** Move BrowserContext and Screen deletion to PostMainMessageLoopRun(),
     so that they may use the MessageLoop during teardown.
  ** Fix Frame dtor to allow for null WindowTreeHosts (headless case)
  ** Fix std::move logic in Frame ctor which lead to no WebContents
     observer being registered.

Bug: 871594

Change-Id: I36bcbd2436d534d366c6be4eeb54b9f9feadd1ac
Reviewed-on: https://chromium-review.googlesource.com/1164539
Commit-Queue: Kevin Marshall <kmarshall@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Reviewed-by: default avatarFabrice de Gans-Riberi <fdegans@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584155}
parent 343657ff
......@@ -4,11 +4,14 @@
#include "content/common/sandbox_policy_fuchsia.h"
#include <fuchsia/fonts/cpp/fidl.h>
#include <lib/fdio/spawn.h>
#include <stdio.h>
#include <zircon/processargs.h>
#include <fuchsia/fonts/cpp/fidl.h>
#include <memory>
#include <utility>
#include "base/base_paths_fuchsia.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
......
......@@ -165,9 +165,33 @@ repack("service_pak") {
output = "$root_out_dir/webrunner.pak"
}
test("webrunner_browsertests") {
sources = [
"browser/context_impl_browsertest.cc",
"browser/webrunner_browser_test.cc",
"browser/webrunner_browser_test.h",
"browser/webrunner_test_launcher.cc",
]
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
data = [
"browser/test/data",
]
deps = [
":fidl",
":service_lib",
"//base/test:test_support",
"//content/test:test_support",
"//net:test_support",
"//testing/gmock",
"//testing/gtest",
"//ui/ozone",
]
}
test("webrunner_unittests") {
sources = [
"service/context_provider_impl_unittest.cc",
# TODO(kmarshall): Uncomment this when the tests are fixed.
# "service/context_provider_impl_unittest.cc",
]
deps = [
":fidl",
......@@ -188,7 +212,6 @@ fidl_library("fidl") {
"fidl/context.fidl",
"fidl/context_provider.fidl",
"fidl/frame.fidl",
"fidl/frame_observer.fidl",
"fidl/navigation_controller.fidl",
]
......
......@@ -6,6 +6,7 @@
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fit/function.h>
#include <utility>
#include <vector>
......@@ -35,9 +36,7 @@ ComponentControllerImpl::CreateForRequest(
}
ComponentControllerImpl::ComponentControllerImpl(WebContentRunner* runner)
: runner_(runner),
controller_binding_(this),
frame_observer_binding_(this) {
: runner_(runner), controller_binding_(this) {
DCHECK(runner);
}
......@@ -67,8 +66,7 @@ bool ComponentControllerImpl::BindToRequest(
fit::bind_member(this, &ComponentControllerImpl::Kill));
}
runner_->context()->CreateFrame(frame_observer_binding_.NewBinding(),
frame_.NewRequest());
runner_->context()->CreateFrame(frame_.NewRequest());
frame_->GetNavigationController(navigation_controller_.NewRequest());
navigation_controller_->LoadUrl(url_.spec(), nullptr);
......@@ -99,10 +97,6 @@ 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::viewsv1token::ViewOwner> view_owner,
fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) {
......
......@@ -26,7 +26,6 @@ class WebContentRunner;
// request. Each ComponentControllerImpl instance manages its own
// chromium::web::Frame.
class ComponentControllerImpl : public fuchsia::sys::ComponentController,
public chromium::web::FrameObserver,
public fuchsia::ui::viewsv1::ViewProvider {
public:
~ComponentControllerImpl() override;
......@@ -46,11 +45,6 @@ class ComponentControllerImpl : public fuchsia::sys::ComponentController,
void Detach() override;
void Wait(WaitCallback callback) override;
// chromium::web::FrameObserver implementation.
void OnNavigationStateChanged(
chromium::web::NavigationStateChangeDetails change,
OnNavigationStateChangedCallback callback) override;
// fuchsia::ui::viewsv1::ViewProvider implementation.
void CreateView(
fidl::InterfaceRequest<::fuchsia::ui::viewsv1token::ViewOwner> view_owner,
......@@ -58,7 +52,7 @@ class ComponentControllerImpl : public fuchsia::sys::ComponentController,
override;
private:
ComponentControllerImpl(WebContentRunner* runner);
explicit ComponentControllerImpl(WebContentRunner* runner);
// Binds |this| to a Runner::StartComponent() call. Returns false on failure
// (e.g. when the URL in |startup_info| is invalid).
......@@ -74,7 +68,6 @@ class ComponentControllerImpl : public fuchsia::sys::ComponentController,
chromium::web::NavigationControllerPtr navigation_controller_;
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_;
......
include_rules = [
"+content/public/browser",
"+content/public/test",
"+ui/aura",
"+ui/display",
"+ui/ozone/public",
"+ui/platform_window",
]
\ No newline at end of file
]
......@@ -4,9 +4,11 @@
#include "webrunner/browser/context_impl.h"
#include <lib/zx/object.h>
#include <memory>
#include <utility>
#include "base/fuchsia/fuchsia_logging.h"
#include "content/public/browser/web_contents.h"
#include "webrunner/browser/frame_impl.h"
......@@ -18,13 +20,42 @@ ContextImpl::ContextImpl(content::BrowserContext* browser_context)
ContextImpl::~ContextImpl() = default;
void ContextImpl::CreateFrame(
fidl::InterfaceHandle<chromium::web::FrameObserver> observer,
fidl::InterfaceRequest<chromium::web::Frame> frame_request) {
auto web_contents = content::WebContents::Create(
content::WebContents::CreateParams(browser_context_, nullptr));
frame_bindings_.AddBinding(
std::make_unique<FrameImpl>(std::move(web_contents), observer.Bind()),
std::move(frame_request));
frames_.insert(std::make_unique<FrameImpl>(std::move(web_contents), this,
std::move(frame_request)));
}
void ContextImpl::DestroyFrame(FrameImpl* frame) {
DCHECK(frames_.find(frame) != frames_.end());
frames_.erase(frames_.find(frame));
}
FrameImpl* ContextImpl::GetFrameImplForTest(
chromium::web::FramePtr* frame_ptr) {
DCHECK(frame_ptr);
// Find the FrameImpl whose channel is connected to |frame_ptr| by inspecting
// the related_koids of active FrameImpls.
zx_info_handle_basic_t handle_info;
zx_status_t status = frame_ptr->channel().get_info(
ZX_INFO_HANDLE_BASIC, &handle_info, sizeof(zx_info_handle_basic_t),
nullptr, nullptr);
ZX_CHECK(status == ZX_OK, status) << "zx_object_get_info";
zx_handle_t client_handle_koid = handle_info.koid;
for (const std::unique_ptr<FrameImpl>& frame : frames_) {
status = frame->GetBindingChannelForTest()->get_info(
ZX_INFO_HANDLE_BASIC, &handle_info, sizeof(zx_info_handle_basic_t),
nullptr, nullptr);
ZX_CHECK(status == ZX_OK, status) << "zx_object_get_info";
if (client_handle_koid == handle_info.related_koid)
return frame.get();
}
return nullptr;
}
} // namespace webrunner
......@@ -7,7 +7,9 @@
#include <lib/fidl/cpp/binding_set.h>
#include <memory>
#include <set>
#include "base/containers/unique_ptr_adapters.h"
#include "base/macros.h"
#include "webrunner/common/webrunner_export.h"
#include "webrunner/fidl/chromium/web/cpp/fidl.h"
......@@ -18,6 +20,8 @@ class BrowserContext;
namespace webrunner {
class FrameImpl;
// 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.
......@@ -29,14 +33,22 @@ class WEBRUNNER_EXPORT ContextImpl : public chromium::web::Context {
// Tears down the Context, destroying any active Frames in the process.
~ContextImpl() override;
// Removes and destroys the specified |frame|.
void DestroyFrame(FrameImpl* frame);
// chromium::web::Context implementation.
void CreateFrame(fidl::InterfaceHandle<chromium::web::FrameObserver> observer,
fidl::InterfaceRequest<chromium::web::Frame> frame) override;
void CreateFrame(fidl::InterfaceRequest<chromium::web::Frame> frame) override;
// Gets the underlying FrameImpl service object associated with a connected
// |frame_ptr| client.
FrameImpl* GetFrameImplForTest(chromium::web::FramePtr* frame_ptr);
private:
content::BrowserContext* browser_context_;
fidl::BindingSet<chromium::web::Frame, std::unique_ptr<chromium::web::Frame>>
frame_bindings_;
// Tracks all active FrameImpl instances, so that we can request their
// destruction when this ContextImpl is destroyed.
std::set<std::unique_ptr<FrameImpl>, base::UniquePtrComparator> frames_;
DISALLOW_COPY_AND_ASSIGN(ContextImpl);
};
......
// 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 <lib/fidl/cpp/binding.h>
#include "base/macros.h"
#include "content/public/browser/web_contents_observer.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/url_constants.h"
#include "webrunner/browser/frame_impl.h"
#include "webrunner/browser/webrunner_browser_test.h"
namespace webrunner {
namespace {
using testing::_;
using testing::AllOf;
using testing::Field;
// Use a shorter name for NavigationStateChangeDetails, because it is
// referenced frequently in this file.
using NavigationDetails = chromium::web::NavigationStateChangeDetails;
const char kPage1Url[] = "/title1.html";
const char kPage2Url[] = "/title2.html";
const char kPage1Title[] = "title 1";
const char kPage2Title[] = "title 2";
MATCHER(IsSet, "Checks if an optional field is set.") {
return !arg.is_null();
}
class ContextImplTest : public WebRunnerBrowserTest {
public:
ContextImplTest() = default;
~ContextImplTest() = default;
protected:
chromium::web::FramePtr CreateFrame() {
chromium::web::FramePtr frame;
context()->CreateFrame(frame.NewRequest());
frame.events().OnNavigationStateChanged =
fit::bind_member(this, &ContextImplTest::OnNavigationStateChanged);
return frame;
}
MOCK_METHOD1(OnNavigationStateChanged,
void(chromium::web::NavigationStateChangeDetails change));
private:
DISALLOW_COPY_AND_ASSIGN(ContextImplTest);
};
class WebContentsDeletionObserver : public content::WebContentsObserver {
public:
WebContentsDeletionObserver(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) {}
MOCK_METHOD1(RenderViewDeleted,
void(content::RenderViewHost* render_view_host));
};
// Verifies that the browser will navigate and generate a navigation observer
// event when LoadUrl() is called.
IN_PROC_BROWSER_TEST_F(ContextImplTest, NavigateFrame) {
chromium::web::FramePtr frame = CreateFrame();
chromium::web::NavigationControllerPtr controller;
frame->GetNavigationController(controller.NewRequest());
base::RunLoop run_loop;
EXPECT_CALL(*this, OnNavigationStateChanged(
Field(&NavigationDetails::title, url::kAboutBlankURL)))
.WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
controller->LoadUrl(url::kAboutBlankURL, nullptr);
run_loop.Run();
frame.Unbind();
}
IN_PROC_BROWSER_TEST_F(ContextImplTest, FrameDeletedBeforeContext) {
chromium::web::FramePtr frame = CreateFrame();
// Process the frame creation message.
base::RunLoop().RunUntilIdle();
FrameImpl* frame_impl = context_impl()->GetFrameImplForTest(&frame);
WebContentsDeletionObserver deletion_observer(
frame_impl->web_contents_for_test());
base::RunLoop run_loop;
EXPECT_CALL(deletion_observer, RenderViewDeleted(_))
.WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
chromium::web::NavigationControllerPtr controller;
frame->GetNavigationController(controller.NewRequest());
controller->LoadUrl(url::kAboutBlankURL, nullptr);
frame.Unbind();
run_loop.Run();
// Check that |context| remains bound after the frame is closed.
EXPECT_TRUE(context());
}
IN_PROC_BROWSER_TEST_F(ContextImplTest, ContextDeletedBeforeFrame) {
chromium::web::FramePtr frame = CreateFrame();
EXPECT_TRUE(frame);
base::RunLoop run_loop;
frame.set_error_handler([&run_loop]() { run_loop.Quit(); });
context().Unbind();
run_loop.Run();
EXPECT_FALSE(frame);
}
IN_PROC_BROWSER_TEST_F(ContextImplTest, GoBackAndForward) {
chromium::web::FramePtr frame = CreateFrame();
chromium::web::NavigationControllerPtr controller;
frame->GetNavigationController(controller.NewRequest());
ASSERT_TRUE(embedded_test_server()->Start());
GURL title1(embedded_test_server()->GetURL(kPage1Url));
GURL title2(embedded_test_server()->GetURL(kPage2Url));
{
base::RunLoop run_loop;
EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf(
Field(&NavigationDetails::title, kPage1Title),
Field(&NavigationDetails::url, IsSet()))))
.WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
controller->LoadUrl(title1.spec(), nullptr);
run_loop.Run();
}
{
base::RunLoop run_loop;
EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf(
Field(&NavigationDetails::title, kPage2Title),
Field(&NavigationDetails::url, IsSet()))))
.WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
controller->LoadUrl(title2.spec(), nullptr);
run_loop.Run();
}
{
base::RunLoop run_loop;
EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf(
Field(&NavigationDetails::title, kPage1Title),
Field(&NavigationDetails::url, IsSet()))))
.WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
controller->GoBack();
run_loop.Run();
}
// At the top of the navigation entry list; this should be a no-op.
controller->GoBack();
// Process the navigation request message.
base::RunLoop().RunUntilIdle();
{
base::RunLoop run_loop;
EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf(
Field(&NavigationDetails::title, kPage2Title),
Field(&NavigationDetails::url, IsSet()))))
.WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
controller->GoForward();
run_loop.Run();
}
// At the end of the navigation entry list; this should be a no-op.
controller->GoForward();
// Process the navigation request message.
base::RunLoop().RunUntilIdle();
}
} // namespace
} // namespace webrunner
......@@ -4,13 +4,19 @@
#include "webrunner/browser/frame_impl.h"
#include <string>
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host_platform.h"
#include "ui/platform_window/platform_window_init_properties.h"
#include "url/gurl.h"
#include "webrunner/browser/context_impl.h"
namespace webrunner {
......@@ -57,14 +63,24 @@ class LayoutManagerImpl : public aura::LayoutManager {
} // namespace
FrameImpl::FrameImpl(std::unique_ptr<content::WebContents> web_contents,
chromium::web::FrameObserverPtr observer)
: web_contents_(std::move(web_contents)), observer_(std::move(observer)) {
Observe(web_contents.get());
ContextImpl* context,
fidl::InterfaceRequest<chromium::web::Frame> frame_request)
: web_contents_(std::move(web_contents)),
context_(context),
binding_(this, std::move(frame_request)) {
binding_.set_error_handler([this]() { context_->DestroyFrame(this); });
Observe(web_contents_.get());
}
FrameImpl::~FrameImpl() {
window_tree_host_->Hide();
window_tree_host_->compositor()->SetVisible(false);
if (window_tree_host_) {
window_tree_host_->Hide();
window_tree_host_->compositor()->SetVisible(false);
}
}
zx::unowned_channel FrameImpl::GetBindingChannelForTest() const {
return zx::unowned_channel(binding_.channel());
}
void FrameImpl::CreateView(
......@@ -103,11 +119,13 @@ void FrameImpl::LoadUrl(fidl::StringPtr url,
}
void FrameImpl::GoBack() {
NOTIMPLEMENTED();
if (web_contents_->GetController().CanGoBack())
web_contents_->GetController().GoBack();
}
void FrameImpl::GoForward() {
NOTIMPLEMENTED();
if (web_contents_->GetController().CanGoForward())
web_contents_->GetController().GoForward();
}
void FrameImpl::Stop() {
......@@ -123,4 +141,28 @@ void FrameImpl::GetVisibleEntry(GetVisibleEntryCallback callback) {
callback(nullptr);
}
void FrameImpl::DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) {
if (web_contents_->GetMainFrame() != render_frame_host) {
return;
}
std::string current_url = validated_url.spec();
std::string current_title = base::UTF16ToUTF8(web_contents_->GetTitle());
bool is_changed;
chromium::web::NavigationStateChangeDetails delta;
if (current_title != cached_navigation_state_.title) {
is_changed = true;
delta.title = current_title;
}
if (current_url != cached_navigation_state_.url) {
is_changed = true;
delta.url = current_url;
}
binding_.events().OnNavigationStateChanged(std::move(delta));
}
} // namespace webrunner
......@@ -6,6 +6,7 @@
#define WEBRUNNER_BROWSER_FRAME_IMPL_H_
#include <lib/fidl/cpp/binding_set.h>
#include <lib/zx/channel.h>
#include <memory>
#include <utility>
......@@ -25,6 +26,8 @@ class WebContents;
namespace webrunner {
class ContextImpl;
// 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,
......@@ -32,9 +35,14 @@ class FrameImpl : public chromium::web::Frame,
public content::WebContentsObserver {
public:
FrameImpl(std::unique_ptr<content::WebContents> web_contents,
chromium::web::FrameObserverPtr observer);
ContextImpl* context,
fidl::InterfaceRequest<chromium::web::Frame> frame_request);
~FrameImpl() override;
zx::unowned_channel GetBindingChannelForTest() const;
content::WebContents* web_contents_for_test() { return web_contents_.get(); }
// content::WebContentsObserver implementation.
void Init(content::BrowserContext* browser_context, const GURL& url);
......@@ -55,11 +63,19 @@ class FrameImpl : public chromium::web::Frame,
void Reload() override;
void GetVisibleEntry(GetVisibleEntryCallback callback) override;
// content::WebContentsObserver implementation.
void DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) override;
private:
std::unique_ptr<aura::WindowTreeHost> window_tree_host_;
std::unique_ptr<content::WebContents> web_contents_;
chromium::web::FrameObserverPtr observer_;
// Cached navigation event details.
chromium::web::NavigationEntry cached_navigation_state_;
ContextImpl* context_ = nullptr;
fidl::Binding<chromium::web::Frame> binding_;
fidl::BindingSet<chromium::web::NavigationController> controller_bindings_;
DISALLOW_COPY_AND_ASSIGN(FrameImpl);
......
<html>
<head><title>title 1</title></head>
<body></body>
</html>
<html>
<head><title>title 2</title></head>
<body></body>
</html>
......@@ -4,6 +4,9 @@
#include "webrunner/browser/webrunner_browser_context.h"
#include <memory>
#include <utility>
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "content/public/browser/browser_thread.h"
......@@ -61,10 +64,14 @@ WebRunnerBrowserContext::WebRunnerBrowserContext(base::FilePath data_dir_path)
}
WebRunnerBrowserContext::~WebRunnerBrowserContext() {
NotifyWillBeDestroyed(this);
if (resource_context_) {
content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
std::move(resource_context_));
}
ShutdownStoragePartitions();
}
std::unique_ptr<content::ZoomLevelDelegate>
......
......@@ -4,6 +4,8 @@
#include "webrunner/browser/webrunner_browser_main_parts.h"
#include <utility>
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "ui/aura/screen_ozone.h"
......@@ -41,16 +43,18 @@ void WebRunnerBrowserMainParts::PreMainMessageLoopRun() {
browser_context_ =
std::make_unique<WebRunnerBrowserContext>(GetWebContextDataDir());
fidl::InterfaceRequest<chromium::web::Context> context_request(
std::move(context_channel_));
context_service_ = std::make_unique<ContextImpl>(browser_context_.get());
context_impl_ = std::make_unique<ContextImpl>(browser_context_.get());
context_binding_ = std::make_unique<fidl::Binding<chromium::web::Context>>(
context_impl_.get(), std::move(context_request));
context_service_.get(), fidl::InterfaceRequest<chromium::web::Context>(
std::move(context_channel_)));
// Quit the context process as soon as context is disconnected.
context_binding_->set_error_handler(
[this]() { std::move(quit_closure_).Run(); });
// Quit the browser main loop when the Context connection is dropped.
context_binding_->set_error_handler([this]() {
DLOG(WARNING) << "Client connection to Context service dropped.";
context_service_.reset();
std::move(quit_closure_).Run();
});
}
void WebRunnerBrowserMainParts::PreDefaultMainMessageLoopRun(
......@@ -58,4 +62,17 @@ void WebRunnerBrowserMainParts::PreDefaultMainMessageLoopRun(
quit_closure_ = std::move(quit_closure);
}
void WebRunnerBrowserMainParts::PostMainMessageLoopRun() {
// The service and its binding should have already been released by the error
// handler.
DCHECK(!context_service_);
DCHECK(!context_binding_->is_bound());
// These resources must be freed while a MessageLoop is still available, so
// that they may post cleanup tasks during teardown.
// NOTE: Please destroy objects in the reverse order of their creation.
browser_context_.reset();
screen_.reset();
}
} // namespace webrunner
......@@ -9,7 +9,9 @@
#include <memory>
#include "base/macros.h"
#include "base/optional.h"
#include "content/public/browser/browser_main_parts.h"
#include "webrunner/browser/context_impl.h"
#include "webrunner/fidl/chromium/web/cpp/fidl.h"
namespace display {
......@@ -18,7 +20,6 @@ class Screen;
namespace webrunner {
class ContextImpl;
class WebRunnerBrowserContext;
class WebRunnerBrowserMainParts : public content::BrowserMainParts {
......@@ -26,17 +27,19 @@ class WebRunnerBrowserMainParts : public content::BrowserMainParts {
explicit WebRunnerBrowserMainParts(zx::channel context_channel);
~WebRunnerBrowserMainParts() override;
ContextImpl* context() { return context_service_.get(); }
// content::BrowserMainParts overrides.
void PreMainMessageLoopRun() override;
void PreDefaultMainMessageLoopRun(base::OnceClosure quit_closure) override;
void PostMainMessageLoopRun() override;
private:
zx::channel context_channel_;
std::unique_ptr<display::Screen> screen_;
std::unique_ptr<WebRunnerBrowserContext> browser_context_;
std::unique_ptr<ContextImpl> context_impl_;
std::unique_ptr<ContextImpl> context_service_;
std::unique_ptr<fidl::Binding<chromium::web::Context>> context_binding_;
base::OnceClosure quit_closure_;
......@@ -46,4 +49,4 @@ class WebRunnerBrowserMainParts : public content::BrowserMainParts {
} // namespace webrunner
#endif // WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_MAIN_PARTS_H_
\ No newline at end of file
#endif // WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_MAIN_PARTS_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/browser/webrunner_browser_test.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "webrunner/browser/webrunner_browser_context.h"
#include "webrunner/browser/webrunner_browser_main_parts.h"
#include "webrunner/browser/webrunner_content_browser_client.h"
#include "webrunner/service/webrunner_main_delegate.h"
namespace webrunner {
namespace {
zx_handle_t g_context_channel = ZX_HANDLE_INVALID;
} // namespace
WebRunnerBrowserTest::WebRunnerBrowserTest() = default;
WebRunnerBrowserTest::~WebRunnerBrowserTest() = default;
void WebRunnerBrowserTest::PreRunTestOnMainThread() {
zx_status_t result = context_.Bind(zx::channel(g_context_channel));
ZX_DCHECK(result == ZX_OK, result) << "Context::Bind";
g_context_channel = ZX_HANDLE_INVALID;
embedded_test_server()->ServeFilesFromSourceDirectory(
"webrunner/browser/test/data");
}
void WebRunnerBrowserTest::PostRunTestOnMainThread() {
// Unbind the Context while the message loops are still alive.
context_.Unbind();
}
// static
void WebRunnerBrowserTest::SetContextClientChannel(zx::channel channel) {
DCHECK(channel);
g_context_channel = channel.release();
}
ContextImpl* WebRunnerBrowserTest::context_impl() const {
return WebRunnerMainDelegate::GetInstanceForTest()
->browser_client()
->main_parts_for_test()
->context();
}
} // 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_BROWSER_WEBRUNNER_BROWSER_TEST_H_
#define WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_TEST_H_
#include <memory>
#include "base/macros.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_base.h"
#include "webrunner/browser/context_impl.h"
#include "webrunner/fidl/chromium/web/cpp/fidl.h"
namespace content {
class BrowserContext;
}
namespace webrunner {
// Base test class used for testing the WebRunner Context FIDL service in
// integration.
class WebRunnerBrowserTest : public content::BrowserTestBase {
public:
WebRunnerBrowserTest();
~WebRunnerBrowserTest() override;
// Sets the Context client channel which will be bound to a Context FIDL
// object by WebRunnerBrowserTest.
static void SetContextClientChannel(zx::channel channel);
// Gets the client object for the Context service.
chromium::web::ContextPtr& context() { return context_; }
// Gets the underlying ContextImpl service instance.
ContextImpl* context_impl() const;
// content::BrowserTestBase implementation.
void PreRunTestOnMainThread() override;
void PostRunTestOnMainThread() override;
private:
chromium::web::ContextPtr context_;
DISALLOW_COPY_AND_ASSIGN(WebRunnerBrowserTest);
};
} // namespace webrunner
#endif // WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_TEST_H_
......@@ -4,6 +4,8 @@
#include "webrunner/browser/webrunner_content_browser_client.h"
#include <utility>
#include "webrunner/browser/webrunner_browser_main_parts.h"
namespace webrunner {
......@@ -18,7 +20,8 @@ content::BrowserMainParts*
WebRunnerContentBrowserClient::CreateBrowserMainParts(
const content::MainFunctionParams& parameters) {
DCHECK(context_channel_);
return new WebRunnerBrowserMainParts(std::move(context_channel_));
main_parts_ = new WebRunnerBrowserMainParts(std::move(context_channel_));
return main_parts_;
}
} // namespace webrunner
\ No newline at end of file
} // namespace webrunner
......@@ -12,17 +12,22 @@
namespace webrunner {
class WebRunnerBrowserMainParts;
class WebRunnerContentBrowserClient : public content::ContentBrowserClient {
public:
explicit WebRunnerContentBrowserClient(zx::channel context_channel);
~WebRunnerContentBrowserClient() override;
WebRunnerBrowserMainParts* main_parts_for_test() const { return main_parts_; }
// ContentBrowserClient overrides.
content::BrowserMainParts* CreateBrowserMainParts(
const content::MainFunctionParams& parameters) override;
private:
zx::channel context_channel_;
WebRunnerBrowserMainParts* main_parts_;
DISALLOW_COPY_AND_ASSIGN(WebRunnerContentBrowserClient);
};
......
// 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 <utility>
#include "base/fuchsia/fuchsia_logging.h"
#include "base/message_loop/message_loop.h"
#include "base/test/test_suite.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_launcher.h"
#include "ui/ozone/public/ozone_switches.h"
#include "webrunner/browser/webrunner_browser_test.h"
#include "webrunner/fidl/chromium/web/cpp/fidl.h"
#include "webrunner/service/common.h"
#include "webrunner/service/webrunner_main_delegate.h"
namespace webrunner {
namespace {
class WebRunnerTestLauncherDelegate : public content::TestLauncherDelegate {
public:
WebRunnerTestLauncherDelegate() = default;
~WebRunnerTestLauncherDelegate() override = default;
// content::TestLauncherDelegate implementation:
int RunTestSuite(int argc, char** argv) override {
return base::TestSuite(argc, argv).Run();
}
bool AdjustChildProcessCommandLine(
base::CommandLine* command_line,
const base::FilePath& temp_data_dir) override {
return true;
}
content::ContentMainDelegate* CreateContentMainDelegate() override {
// Set up the channels for the Context service, but postpone client
// binding until after the browser TaskRunners are up and running.
zx::channel server_channel;
zx::channel client_channel;
zx_status_t result =
zx::channel::create(0, &client_channel, &server_channel);
ZX_CHECK(result == ZX_OK, result) << "zx::channel::create";
WebRunnerBrowserTest::SetContextClientChannel(std::move(client_channel));
return new webrunner::WebRunnerMainDelegate(std::move(server_channel));
}
private:
chromium::web::ContextPtr context_;
DISALLOW_COPY_AND_ASSIGN(WebRunnerTestLauncherDelegate);
};
} // namespace
} // namespace webrunner
int main(int argc, char** argv) {
base::CommandLine::Init(argc, argv);
base::CommandLine::ForCurrentProcess()->AppendSwitch(
webrunner::kIncognitoSwitch);
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kOzonePlatform, "headless");
base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kDisableGpu);
size_t parallel_jobs = base::NumParallelJobs();
if (parallel_jobs > 1U) {
parallel_jobs /= 2U;
}
webrunner::WebRunnerTestLauncherDelegate launcher_delegate;
return LaunchTests(&launcher_delegate, parallel_jobs, argc, argv);
}
......@@ -9,8 +9,6 @@ library chromium.web;
interface Context {
// Creates a new frame under this Context.
//
// |observer|: An observer service, provided by the caller, which receives
// events originating from |frame|.
// |frame|: An interface request that will be bound to the created Frame.
1: CreateFrame(FrameObserver observer, request<Frame> frame);
1: CreateFrame(request<Frame> frame);
};
......@@ -4,6 +4,14 @@
library chromium.web;
// Indicates which properties of the NavigationController's visible content
// that have changed since the last OnNavigationStateChanged() event.
// Properties which remain unchanged are left unset.
struct NavigationStateChangeDetails {
string? url;
string? title;
};
interface Frame {
// Creates and registers a view with the view manager and returns its
// view owner which may subsequently be passed to |View.AddChild()|
......@@ -20,4 +28,7 @@ interface Frame {
// |view_provider|: An interface request for the Frame's
// NavigationController.
2: GetNavigationController(request<NavigationController> controller);
// Called when user-visible navigation state has changed for the Frame.
3: -> OnNavigationStateChanged(NavigationStateChangeDetails change);
};
// 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.
library chromium.web;
// Interface supplied by the embedder for receiving notifications about
// changes in a Frame.
interface FrameObserver {
// Called when user-visible navigation state has changed for the Frame.
1: OnNavigationStateChanged(NavigationStateChangeDetails change) -> ();
};
// Indicates which properties of the NavigationController's visible content
// that have changed since the last OnNavigationStateChanged() event.
struct NavigationStateChangeDetails {
bool url_changed;
bool title_changed;
// The Frame's visible navigation state, captured at the time the event was
// fired.
NavigationEntry entry;
};
......@@ -26,7 +26,7 @@ extern const char kWebContextDataPath[];
// Switch passed to content process when running in incognito mode, i.e. when
// there is no kWebContextDataPath.
extern const char kIncognitoSwitch[];
WEBRUNNER_EXPORT extern const char kIncognitoSwitch[];
// Returns data directory that should be used by this context process. Should
// not be called in ContextProvider. Empty path is returned if the context
......
......@@ -4,6 +4,8 @@
#include "webrunner/service/webrunner_main_delegate.h"
#include <utility>
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/path_service.h"
......@@ -15,9 +17,10 @@
#include "webrunner/service/common.h"
namespace webrunner {
namespace {
WebRunnerMainDelegate* g_current_webrunner_main_delegate = nullptr;
void InitLoggingFromCommandLine(const base::CommandLine& command_line) {
base::FilePath log_filename;
std::string filename = command_line.GetSwitchValueASCII(switches::kLogFile);
......@@ -47,8 +50,16 @@ void InitializeResourceBundle() {
} // namespace
// static
WebRunnerMainDelegate* WebRunnerMainDelegate::GetInstanceForTest() {
return g_current_webrunner_main_delegate;
}
WebRunnerMainDelegate::WebRunnerMainDelegate(zx::channel context_channel)
: context_channel_(std::move(context_channel)) {}
: context_channel_(std::move(context_channel)) {
DCHECK(context_channel_);
g_current_webrunner_main_delegate = this;
}
WebRunnerMainDelegate::~WebRunnerMainDelegate() = default;
......@@ -75,6 +86,7 @@ int WebRunnerMainDelegate::RunProcess(
content::ContentBrowserClient*
WebRunnerMainDelegate::CreateContentBrowserClient() {
DCHECK(context_channel_);
DCHECK(!browser_client_);
browser_client_ = std::make_unique<WebRunnerContentBrowserClient>(
std::move(context_channel_));
......
......@@ -7,6 +7,7 @@
#include <lib/zx/channel.h>
#include <memory>
#include <string>
#include "base/macros.h"
#include "content/public/app/content_main_delegate.h"
......@@ -18,12 +19,20 @@ class ContentClient;
namespace webrunner {
class WebRunnerContentBrowserClient;
class WEBRUNNER_EXPORT WebRunnerMainDelegate
: public content::ContentMainDelegate {
public:
explicit WebRunnerMainDelegate(zx::channel context_channel);
~WebRunnerMainDelegate() override;
static WebRunnerMainDelegate* GetInstanceForTest();
WebRunnerContentBrowserClient* browser_client() {
return browser_client_.get();
}
// ContentMainDelegate implementation.
bool BasicStartupComplete(int* exit_code) override;
void PreSandboxStartup() override;
......@@ -34,7 +43,7 @@ class WEBRUNNER_EXPORT WebRunnerMainDelegate
private:
std::unique_ptr<content::ContentClient> content_client_;
std::unique_ptr<content::ContentBrowserClient> browser_client_;
std::unique_ptr<WebRunnerContentBrowserClient> browser_client_;
zx::channel context_channel_;
......
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