blob: 12df9e4eaf8e071cf886105b09400b92b01c84ed [file] [log] [blame]
// Copyright 2021 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/io/cpp/fidl.h>
#include <fuchsia/web/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/sys/cpp/component_context.h>
#include "base/command_line.h"
#include "base/files/file_enumerator.h"
#include "base/fuchsia/filtered_service_directory.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/fuchsia/process_context.h"
#include "base/strings/string_piece_forward.h"
#include "base/test/task_environment.h"
#include "fuchsia/base/test/fit_adapter.h"
#include "fuchsia/base/test/frame_test_util.h"
#include "fuchsia/base/test/result_receiver.h"
#include "fuchsia/base/test/test_devtools_list_fetcher.h"
#include "fuchsia/base/test/test_navigation_listener.h"
#include "fuchsia/engine/test/frame_for_test.h"
#include "fuchsia/engine/web_instance_host/web_instance_host.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
class WebInstanceHostIntegrationTest : public testing::Test {
public:
WebInstanceHostIntegrationTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
filtered_service_directory_(
base::ComponentContextForProcess()->svc().get()) {
// Push all services from /svc to the filtered service directory.
base::FileEnumerator file_enum(base::FilePath("/svc"), false,
base::FileEnumerator::FILES);
for (auto file = file_enum.Next(); !file.empty(); file = file_enum.Next()) {
zx_status_t status = filtered_service_directory_.AddService(
file_enum.GetInfo().GetName().value().c_str());
ZX_CHECK(status == ZX_OK, status)
<< "FilteredServiceDirectory::AddService";
}
}
~WebInstanceHostIntegrationTest() override = default;
WebInstanceHostIntegrationTest(const WebInstanceHostIntegrationTest&) =
delete;
WebInstanceHostIntegrationTest& operator=(
const WebInstanceHostIntegrationTest&) = delete;
void SetUp() override {
// Override command line. This is necessary to get WebEngine logs.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitchASCII("enable-logging", "stderr");
embedded_test_server_.ServeFilesFromSourceDirectory(
"fuchsia/engine/test/data");
net::test_server::RegisterDefaultHandlers(&embedded_test_server_);
CHECK(embedded_test_server_.Start());
}
protected:
fuchsia::web::CreateContextParams TestContextParams() {
fuchsia::web::CreateContextParams create_params;
zx_status_t status = filtered_service_directory_.ConnectClient(
create_params.mutable_service_directory()->NewRequest());
ZX_CHECK(status == ZX_OK, status)
<< "FilteredServiceDirectory::ConnectClient";
return create_params;
}
void CreateContext(fuchsia::web::CreateContextParams context_params) {
CHECK(!context_);
fuchsia::io::DirectoryHandle web_instance_services;
web_instance_host_.CreateInstanceForContext(
std::move(context_params), web_instance_services.NewRequest());
web_instance_services_ = std::make_unique<sys::ServiceDirectory>(
std::move(web_instance_services));
zx_status_t result = web_instance_services_->Connect(context_.NewRequest());
ZX_CHECK(result == ZX_OK, result) << "fdio_service_connect_at";
context_.set_error_handler([](zx_status_t status) { ADD_FAILURE(); });
}
void ConnectFrameHost() {
zx_status_t result =
web_instance_services_->Connect(frame_host_.NewRequest());
ZX_CHECK(result == ZX_OK, result) << "fdio_service_connect_at";
frame_host_.set_error_handler([](zx_status_t status) { ADD_FAILURE(); });
}
const base::test::TaskEnvironment task_environment_;
fidl::InterfaceHandle<fuchsia::sys::ComponentController>
web_engine_controller_;
cr_fuchsia::WebInstanceHost web_instance_host_;
std::unique_ptr<sys::ServiceDirectory> web_instance_services_;
fuchsia::web::ContextPtr context_;
fuchsia::web::FrameHostPtr frame_host_;
net::EmbeddedTestServer embedded_test_server_;
base::FilteredServiceDirectory filtered_service_directory_;
};
// Check that connecting and disconnecting to the FrameHost service does not
// trigger shutdown of the devtools service.
TEST_F(WebInstanceHostIntegrationTest, FrameHostDebugging) {
fuchsia::web::CreateContextParams create_params = TestContextParams();
create_params.set_remote_debugging_port(0);
CreateContext(std::move(create_params));
fuchsia::web::CreateFrameParams create_frame_params;
create_frame_params.set_enable_remote_debugging(true);
auto frame = cr_fuchsia::FrameForTest::Create(context_,
std::move(create_frame_params));
// Expect to receive a notification of the selected DevTools port.
base::RunLoop run_loop;
cr_fuchsia::ResultReceiver<
fuchsia::web::Context_GetRemoteDebuggingPort_Result>
port_receiver(run_loop.QuitClosure());
context_->GetRemoteDebuggingPort(
cr_fuchsia::CallbackToFitFunction(port_receiver.GetReceiveCallback()));
run_loop.Run();
ASSERT_TRUE(port_receiver->is_response());
uint16_t remote_debugging_port = port_receiver->response().port;
ASSERT_TRUE(remote_debugging_port != 0);
// Navigate to a URL, the devtools service should be active and report a
// single page.
GURL url = embedded_test_server_.GetURL("/defaultresponse");
ASSERT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
frame.GetNavigationController(), fuchsia::web::LoadUrlParams(),
url.spec()));
frame.navigation_listener().RunUntilUrlEquals(url);
base::Value devtools_list =
cr_fuchsia::GetDevToolsListFromPort(remote_debugging_port);
ASSERT_TRUE(devtools_list.is_list());
EXPECT_EQ(devtools_list.GetList().size(), 1u);
base::Value* devtools_url = devtools_list.GetList()[0].FindPath("url");
ASSERT_TRUE(devtools_url->is_string());
EXPECT_EQ(devtools_url->GetString(), url);
// Connect to the FrameHost and immediately disconnect it.
ConnectFrameHost();
frame_host_.Unbind();
// Navigate to a different page. The devtools service should still be active
// and report the new page.
GURL url2 = embedded_test_server_.GetURL("/title1.html");
ASSERT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
frame.GetNavigationController(), fuchsia::web::LoadUrlParams(),
url2.spec()));
frame.navigation_listener().RunUntilUrlEquals(url2);
devtools_list = cr_fuchsia::GetDevToolsListFromPort(remote_debugging_port);
ASSERT_TRUE(devtools_list.is_list());
EXPECT_EQ(devtools_list.GetList().size(), 1u);
devtools_url = devtools_list.GetList()[0].FindPath("url");
ASSERT_TRUE(devtools_url->is_string());
EXPECT_EQ(devtools_url->GetString(), url2);
}