Commit 832c61f6 authored by Fabrice de Gans-Riberi's avatar Fabrice de Gans-Riberi Committed by Commit Bot

[fuchsia] Add CastAgent-provided headers to LoadUrl in CastRunner.

* Modify WebComponent and WebContentRunner to take optional extra
  headers to pass to LoadUrl().

Bug: 977753
Change-Id: I7d23b57629831b775e23ca19a0d0d96886155e6b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1672528
Commit-Queue: Fabrice de Gans-Riberi <fdegans@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#672655}
parent a8732c9a
......@@ -29,6 +29,8 @@ struct CastRunner::PendingComponent {
std::unique_ptr<ApiBindingsClient> bindings_manager;
fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller_request;
chromium::cast::ApplicationConfig app_config;
fuchsia::web::AdditionalHeadersProviderPtr headers_provider;
base::Optional<std::vector<fuchsia::net::http::Header>> headers;
};
void CastRunner::StartComponent(
......@@ -78,6 +80,28 @@ void CastRunner::StartComponent(
base::BindOnce(&CastRunner::MaybeStartComponent, base::Unretained(this),
base::Unretained(pending_component.get())));
// Get AdditionalHeadersProvider from the Agent.
fidl::InterfaceHandle<fuchsia::web::AdditionalHeadersProvider>
additional_headers_provider;
pending_component->agent_manager->ConnectToAgentService(
kAgentComponentUrl, additional_headers_provider.NewRequest());
pending_component->headers_provider = additional_headers_provider.Bind();
pending_component->headers_provider.set_error_handler(
[this, pending_component = pending_component.get()](zx_status_t error) {
if (pending_component->headers.has_value())
return;
pending_component->headers = {};
MaybeStartComponent(pending_component);
});
pending_component->headers_provider->GetHeaders(
[this, pending_component = pending_component.get()](
std::vector<fuchsia::net::http::Header> headers, zx_time_t expiry) {
pending_component->headers =
base::Optional<std::vector<fuchsia::net::http::Header>>(
std::move(headers));
MaybeStartComponent(pending_component);
});
const std::string cast_app_id(cast_url.GetContent());
pending_component->app_config_manager->GetConfig(
cast_app_id, [this, pending_component = pending_component.get()](
......@@ -114,14 +138,12 @@ void CastRunner::GetConfigCallback(
}
void CastRunner::MaybeStartComponent(PendingComponent* pending_component) {
// Called after the completion of GetConfigCallback() or
// ApiBindingsClient::OnBindingsReceived().
if (pending_component->app_config.IsEmpty() ||
!pending_component->bindings_manager->HasBindings()) {
// Don't proceed unless both the application config and API bindings are
// received.
if (pending_component->app_config.IsEmpty())
return;
if (!pending_component->bindings_manager->HasBindings())
return;
if (!pending_component->headers.has_value())
return;
}
// Create a component based on the returned configuration, and pass it the
// fields stashed in PendingComponent.
......@@ -132,8 +154,10 @@ void CastRunner::MaybeStartComponent(PendingComponent* pending_component) {
std::move(pending_component->startup_context),
std::move(pending_component->controller_request),
std::move(pending_component->agent_manager));
std::vector<fuchsia::net::http::Header> additional_headers =
pending_component->headers.value();
pending_components_.erase(pending_component);
component->LoadUrl(std::move(cast_app_url));
component->LoadUrl(std::move(cast_app_url), std::move(additional_headers));
RegisterComponent(std::move(component));
}
......@@ -14,17 +14,21 @@
#include "base/strings/stringprintf.h"
#include "base/test/bind_test_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "fuchsia/base/agent_impl.h"
#include "fuchsia/base/fake_component_context.h"
#include "fuchsia/base/fit_adapter.h"
#include "fuchsia/base/mem_buffer_util.h"
#include "fuchsia/base/result_receiver.h"
#include "fuchsia/base/test_navigation_listener.h"
#include "fuchsia/runners/cast/cast_runner.h"
#include "fuchsia/runners/cast/fake_application_config_manager.h"
#include "fuchsia/runners/cast/test_api_bindings.h"
#include "fuchsia/runners/common/web_component.h"
#include "fuchsia/runners/common/web_content_runner.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/http_request.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace castrunner {
......@@ -39,6 +43,35 @@ void ComponentErrorHandler(zx_status_t status) {
ADD_FAILURE();
}
std::vector<uint8_t> StringToUnsignedVector(base::StringPiece str) {
const uint8_t* raw_data = reinterpret_cast<const uint8_t*>(str.data());
return std::vector<uint8_t>(raw_data, raw_data + str.length());
}
class FakeAdditionalHeadersProvider
: public fuchsia::web::AdditionalHeadersProvider {
public:
FakeAdditionalHeadersProvider(base::fuchsia::ServiceDirectory* directory)
: binding_(directory, this) {}
~FakeAdditionalHeadersProvider() override = default;
private:
void GetHeaders(GetHeadersCallback callback) override {
std::vector<fuchsia::net::http::Header> headers;
fuchsia::net::http::Header header;
header.name = StringToUnsignedVector("Test");
header.value = StringToUnsignedVector("Value");
headers.push_back(std::move(header));
callback(std::move(headers), 0);
}
const base::fuchsia::ScopedServiceBinding<
fuchsia::web::AdditionalHeadersProvider>
binding_;
DISALLOW_COPY_AND_ASSIGN(FakeAdditionalHeadersProvider);
};
class FakeComponentState : public cr_fuchsia::AgentImpl::ComponentStateBase {
public:
FakeComponentState(
......@@ -46,7 +79,10 @@ class FakeComponentState : public cr_fuchsia::AgentImpl::ComponentStateBase {
chromium::cast::ApplicationConfigManager* app_config_manager,
chromium::cast::ApiBindings* bindings_manager)
: ComponentStateBase(component_url),
app_config_binding_(service_directory(), app_config_manager) {
app_config_binding_(service_directory(), app_config_manager),
additional_headers_provider_(
std::make_unique<FakeAdditionalHeadersProvider>(
service_directory())) {
if (bindings_manager) {
bindings_manager_binding_ = std::make_unique<
base::fuchsia::ScopedServiceBinding<chromium::cast::ApiBindings>>(
......@@ -69,6 +105,7 @@ class FakeComponentState : public cr_fuchsia::AgentImpl::ComponentStateBase {
std::unique_ptr<
base::fuchsia::ScopedServiceBinding<chromium::cast::ApiBindings>>
bindings_manager_binding_;
std::unique_ptr<FakeAdditionalHeadersProvider> additional_headers_provider_;
base::OnceClosure on_delete_;
DISALLOW_COPY_AND_ASSIGN(FakeComponentState);
......@@ -297,4 +334,59 @@ TEST_F(CastRunnerIntegrationTest, IncorrectCastAppId) {
EXPECT_FALSE(web_component.has_value());
}
TEST_F(CastRunnerIntegrationTest, AdditionalHeadersProvider) {
const char kEchoAppId[] = "00000000";
const char kEchoAppPath[] = "/echoheader?Test";
const GURL echo_app_url = test_server_.GetURL(kEchoAppPath);
app_config_manager_.AddAppMapping(kEchoAppId, echo_app_url);
// Launch the test-app component.
fuchsia::sys::ComponentControllerPtr component_controller =
StartCastComponent(base::StringPrintf("cast:%s", kEchoAppId));
component_controller.set_error_handler(&ComponentErrorHandler);
WebComponent* web_component = nullptr;
{
base::RunLoop run_loop;
cr_fuchsia::ResultReceiver<WebComponent*> web_component_receiver(
run_loop.QuitClosure());
cast_runner_->GetWebComponentForTest(
web_component_receiver.GetReceiveCallback());
run_loop.Run();
ASSERT_NE(*web_component_receiver, nullptr);
web_component = *web_component_receiver;
}
// Bind a TestNavigationListener to the Frame.
cr_fuchsia::TestNavigationListener navigation_listener;
fidl::Binding<fuchsia::web::NavigationEventListener>
navigation_listener_binding(&navigation_listener);
web_component->frame()->SetNavigationEventListener(
navigation_listener_binding.NewBinding());
navigation_listener.RunUntilUrlEquals(echo_app_url);
// Check the header was properly set.
{
base::RunLoop run_loop;
web_component->frame()->ExecuteJavaScript(
{echo_app_url.GetOrigin().spec()},
cr_fuchsia::MemBufferFromString("document.body.innerText"),
[&](fuchsia::web::Frame_ExecuteJavaScript_Result result) {
ASSERT_TRUE(result.is_response());
std::string result_json;
ASSERT_TRUE(cr_fuchsia::StringFromMemBuffer(result.response().result,
&result_json));
EXPECT_EQ(result_json, "\"Value\"");
run_loop.Quit();
});
run_loop.Run();
}
// Shutdown the component and wait for the teardown of its state.
base::RunLoop run_loop;
component_state_->set_on_delete(run_loop.QuitClosure());
component_controller.Unbind();
run_loop.Run();
}
} // namespace castrunner
......@@ -74,7 +74,9 @@ WebComponent::~WebComponent() {
termination_reason_);
}
void WebComponent::LoadUrl(const GURL& url) {
void WebComponent::LoadUrl(
const GURL& url,
std::vector<fuchsia::net::http::Header> extra_headers) {
DCHECK(url.is_valid());
fuchsia::web::NavigationControllerPtr navigation_controller;
frame()->GetNavigationController(navigation_controller.NewRequest());
......@@ -84,6 +86,8 @@ void WebComponent::LoadUrl(const GURL& url) {
// content.
fuchsia::web::LoadUrlParams params;
params.set_was_user_activated(true);
if (!extra_headers.empty())
params.set_headers(std::move(extra_headers));
navigation_controller->LoadUrl(
url.spec(), std::move(params),
......
......@@ -45,8 +45,9 @@ class WebComponent : public fuchsia::sys::ComponentController,
~WebComponent() override;
// Navigates this component's Frame to |url|.
void LoadUrl(const GURL& url);
// Navigates this component's Frame to |url| and passes |extra_headers|.
void LoadUrl(const GURL& url,
std::vector<fuchsia::net::http::Header> extra_headers);
fuchsia::web::Frame* frame() const { return frame_.get(); }
......
......@@ -94,7 +94,7 @@ void WebContentRunner::StartComponent(
this,
std::make_unique<base::fuchsia::StartupContext>(std::move(startup_info)),
std::move(controller_request));
component->LoadUrl(url);
component->LoadUrl(url, std::vector<fuchsia::net::http::Header>());
RegisterComponent(std::move(component));
}
......
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