Commit 2d3d8f0e authored by Kevin Marshall's avatar Kevin Marshall Committed by Commit Bot

[CastRunner] Add support for isolated components in CastRunner.

* Adds support for isolated CastRunner instances, which run without
  networking capabilities and only have access to resources served
  by local ContentDirectoryProviders.
* Defers web.Context creation to WebComponent creation time, so that
  CastRunner can defer shared Context creation until it's actually
  needed.

Bug: 1004505
Change-Id: I4af9ca7c04b9c86e93c30b2d0aaa7f39ee3f8d5f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1808159
Commit-Queue: Kevin Marshall <kmarshall@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#705634}
parent 32c2d184
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
library chromium.cast; library chromium.cast;
using fuchsia.web;
/// Describes the configuration under which a Cast application should run. /// Describes the configuration under which a Cast application should run.
table ApplicationConfig { table ApplicationConfig {
/// Cast application Id. /// Cast application Id.
...@@ -21,6 +23,11 @@ table ApplicationConfig { ...@@ -21,6 +23,11 @@ table ApplicationConfig {
// If true, enable remote debugging for this application. // If true, enable remote debugging for this application.
// if false or unset, remote debugging is disabled for this application. // if false or unset, remote debugging is disabled for this application.
5: bool enable_remote_debugging; 5: bool enable_remote_debugging;
/// List of directories whose contents are served via `fuchsia-dir://`
/// URLs. Networking will be disabled if any directories are set.
6: vector<fuchsia.web.ContentDirectoryProvider>
content_directories_for_isolated_application;
}; };
/// Service interface for working with application configurations. /// Service interface for working with application configurations.
......
...@@ -4,20 +4,72 @@ ...@@ -4,20 +4,72 @@
#include "fuchsia/runners/cast/cast_runner.h" #include "fuchsia/runners/cast/cast_runner.h"
#include <fuchsia/sys/cpp/fidl.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include "base/fuchsia/file_utils.h"
#include "base/fuchsia/fuchsia_logging.h" #include "base/fuchsia/fuchsia_logging.h"
#include "base/logging.h" #include "base/logging.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace {
bool AreCastComponentParamsValid(
const CastComponent::CastComponentParams& params) {
if (params.app_config.IsEmpty())
return false;
if (!params.api_bindings_client->HasBindings())
return false;
if (!params.rewrite_rules.has_value())
return false;
return true;
}
// Creates a CreateContextParams object which can be used as a basis
// for starting isolated Runners.
fuchsia::web::CreateContextParams BuildCreateContextParamsForIsolatedRunners(
const fuchsia::web::CreateContextParams& create_context_params) {
fuchsia::web::CreateContextParams output;
if (create_context_params.has_features()) {
output.set_features(create_context_params.features());
}
if (create_context_params.has_user_agent_product()) {
output.set_user_agent_product(create_context_params.user_agent_product());
}
if (create_context_params.has_user_agent_version()) {
output.set_user_agent_version(create_context_params.user_agent_version());
}
if (create_context_params.has_remote_debugging_port()) {
output.set_remote_debugging_port(
create_context_params.remote_debugging_port());
}
return output;
}
} // namespace
CastRunner::CastRunner(sys::OutgoingDirectory* outgoing_directory, CastRunner::CastRunner(sys::OutgoingDirectory* outgoing_directory,
fuchsia::web::CreateContextParams create_context_params)
: WebContentRunner(outgoing_directory,
base::BindOnce(&CastRunner::CreateCastRunnerWebContext,
base::Unretained(this))),
create_context_params_(std::move(create_context_params)),
common_create_context_params_(
BuildCreateContextParamsForIsolatedRunners(create_context_params_)) {}
CastRunner::CastRunner(OnDestructionCallback on_destruction_callback,
fuchsia::web::ContextPtr context) fuchsia::web::ContextPtr context)
: WebContentRunner(outgoing_directory, std::move(context)) {} : WebContentRunner(std::move(context)),
on_destruction_callback_(std::move(on_destruction_callback)) {}
CastRunner::~CastRunner() = default; CastRunner::~CastRunner() = default;
fuchsia::web::ContextPtr CastRunner::CreateCastRunnerWebContext() {
return WebContentRunner::CreateWebContext(std::move(create_context_params_));
}
void CastRunner::StartComponent( void CastRunner::StartComponent(
fuchsia::sys::Package package, fuchsia::sys::Package package,
fuchsia::sys::StartupInfo startup_info, fuchsia::sys::StartupInfo startup_info,
...@@ -99,6 +151,16 @@ void CastRunner::StartComponent( ...@@ -99,6 +151,16 @@ void CastRunner::StartComponent(
pending_components_.emplace(std::move(pending_component)); pending_components_.emplace(std::move(pending_component));
} }
void CastRunner::DestroyComponent(WebComponent* component) {
WebContentRunner::DestroyComponent(component);
if (on_destruction_callback_) {
// |this| may be deleted and should not be used after this line.
std::move(on_destruction_callback_).Run(this);
return;
}
}
const char CastRunner::kAgentComponentUrl[] = const char CastRunner::kAgentComponentUrl[] =
"fuchsia-pkg://fuchsia.com/cast_agent#meta/cast_agent.cmx"; "fuchsia-pkg://fuchsia.com/cast_agent#meta/cast_agent.cmx";
...@@ -121,23 +183,75 @@ void CastRunner::GetConfigCallback( ...@@ -121,23 +183,75 @@ void CastRunner::GetConfigCallback(
} }
void CastRunner::MaybeStartComponent( void CastRunner::MaybeStartComponent(
CastComponent::CastComponentParams* pending_component) { CastComponent::CastComponentParams* pending_component_params) {
if (pending_component->app_config.IsEmpty()) if (!AreCastComponentParamsValid(*pending_component_params))
return;
if (!pending_component->api_bindings_client->HasBindings())
return;
if (!pending_component->rewrite_rules.has_value())
return; return;
// Create a component based on the returned configuration, and pass it the // The runner which will host the newly created CastComponent.
// |pending_component|. CastRunner* component_owner = this;
GURL cast_app_url(pending_component->app_config.web_url()); if (pending_component_params->app_config
auto component = .has_content_directories_for_isolated_application()) {
std::make_unique<CastComponent>(this, std::move(*pending_component)); // Create a isolated, isolated CastRunner instance which will own the
pending_components_.erase(pending_component); // CastComponent.
component_owner =
component->StartComponent(); CreateChildRunnerForIsolatedComponent(pending_component_params);
component->LoadUrl(std::move(cast_app_url), }
std::vector<fuchsia::net::http::Header>());
RegisterComponent(std::move(component)); component_owner->CreateAndRegisterCastComponent(
std::move(*pending_component_params));
pending_components_.erase(pending_component_params);
}
void CastRunner::CreateAndRegisterCastComponent(
CastComponent::CastComponentParams params) {
GURL app_url = GURL(params.app_config.web_url());
auto cast_component =
std::make_unique<CastComponent>(this, std::move(params));
cast_component->StartComponent();
cast_component->LoadUrl(std::move(app_url),
std::vector<fuchsia::net::http::Header>());
RegisterComponent(std::move(cast_component));
}
CastRunner* CastRunner::CreateChildRunnerForIsolatedComponent(
CastComponent::CastComponentParams* params) {
// Construct the CreateContextParams in order to create a new Context.
// Some common parameters must be inherited from
// |common_create_context_params_|.
fuchsia::web::CreateContextParams isolated_context_params;
zx_status_t status =
common_create_context_params_.Clone(&isolated_context_params);
ZX_CHECK(status == ZX_OK, status) << "clone";
isolated_context_params.set_service_directory(base::fuchsia::OpenDirectory(
base::FilePath(base::fuchsia::kServiceDirectoryPath)));
isolated_context_params.set_content_directories(
std::move(*params->app_config
.mutable_content_directories_for_isolated_application()));
std::unique_ptr<CastRunner> cast_runner(
new CastRunner(base::BindOnce(&CastRunner::OnChildRunnerDestroyed,
base::Unretained(this)),
CreateWebContext(std::move(isolated_context_params))));
// If test code is listening for Component creation events, then wire up the
// isolated CastRunner to signal component creation events.
if (web_component_created_callback_for_test()) {
cast_runner->SetWebComponentCreatedCallbackForTest(
web_component_created_callback_for_test());
}
CastRunner* cast_runner_ptr = cast_runner.get();
isolated_runners_.insert(std::move(cast_runner));
return cast_runner_ptr;
}
void CastRunner::OnChildRunnerDestroyed(CastRunner* runner) {
auto runner_iterator = isolated_runners_.find(runner);
DCHECK(runner_iterator != isolated_runners_.end());
isolated_runners_.erase(runner_iterator);
}
size_t CastRunner::GetChildCastRunnerCountForTest() {
return isolated_runners_.size();
} }
...@@ -22,11 +22,20 @@ ...@@ -22,11 +22,20 @@
// sys::Runner which instantiates Cast activities specified via cast/casts URIs. // sys::Runner which instantiates Cast activities specified via cast/casts URIs.
class CastRunner : public WebContentRunner { class CastRunner : public WebContentRunner {
public: public:
using OnDestructionCallback = base::OnceCallback<void(CastRunner*)>;
// |outgoing_directory|: The directory that this CastRunner will publish
// itself to.
// |context_feature_flags|: The feature flags to use when creating the
// runner's Context.
CastRunner(sys::OutgoingDirectory* outgoing_directory, CastRunner(sys::OutgoingDirectory* outgoing_directory,
fuchsia::web::ContextPtr context); fuchsia::web::CreateContextParams create_context_params);
~CastRunner() override; ~CastRunner() override;
// WebContentRunner implementation.
void DestroyComponent(WebComponent* component) override;
// fuchsia::sys::Runner implementation. // fuchsia::sys::Runner implementation.
void StartComponent(fuchsia::sys::Package package, void StartComponent(fuchsia::sys::Package package,
fuchsia::sys::StartupInfo startup_info, fuchsia::sys::StartupInfo startup_info,
...@@ -36,16 +45,35 @@ class CastRunner : public WebContentRunner { ...@@ -36,16 +45,35 @@ class CastRunner : public WebContentRunner {
// Used to connect to the CastAgent to access Cast-specific services. // Used to connect to the CastAgent to access Cast-specific services.
static const char kAgentComponentUrl[]; static const char kAgentComponentUrl[];
// Returns the number of active CastRunner instances.
size_t GetChildCastRunnerCountForTest();
private: private:
// Constructor used for creating CastRunners that run apps in dedicated
// Contexts. Child CastRunners may only spawn one Component and will be
// destroyed by their parents when their singleton Components are destroyed.
// |on_destruction_callback| is invoked when the child component is destroyed.
CastRunner(OnDestructionCallback on_destruction_callback,
fuchsia::web::ContextPtr context);
// Starts a component once all configuration data is available.
void MaybeStartComponent(
CastComponent::CastComponentParams* pending_component_params);
void CreateAndRegisterCastComponent(
CastComponent::CastComponentParams params);
void GetConfigCallback(CastComponent::CastComponentParams* pending_component, void GetConfigCallback(CastComponent::CastComponentParams* pending_component,
chromium::cast::ApplicationConfig app_config); chromium::cast::ApplicationConfig app_config);
void GetBindingsCallback( void GetBindingsCallback(
CastComponent::CastComponentParams* pending_component, CastComponent::CastComponentParams* pending_component,
std::vector<chromium::cast::ApiBinding> bindings); std::vector<chromium::cast::ApiBinding> bindings);
void OnChildRunnerDestroyed(CastRunner* cast_runner);
fuchsia::web::ContextPtr CreateCastRunnerWebContext();
// Starts a component once all configuration data is available. // Creates a CastRunner configured to serve data from content directories in
void MaybeStartComponent( // |params|.
CastComponent::CastComponentParams* pending_component); CastRunner* CreateChildRunnerForIsolatedComponent(
CastComponent::CastComponentParams* params);
// Holds StartComponent() requests while the ApplicationConfig is being // Holds StartComponent() requests while the ApplicationConfig is being
// fetched from the ApplicationConfigManager. // fetched from the ApplicationConfigManager.
...@@ -53,6 +81,20 @@ class CastRunner : public WebContentRunner { ...@@ -53,6 +81,20 @@ class CastRunner : public WebContentRunner {
base::UniquePtrComparator> base::UniquePtrComparator>
pending_components_; pending_components_;
// Used for creating the CastRunner's ContextPtr.
fuchsia::web::CreateContextParams create_context_params_;
// Used as a template for creating the ContextPtrs of isolated Runners.
fuchsia::web::CreateContextParams common_create_context_params_;
// Invoked upon destruction of "isolated" runners, used to signal termination
// to parents.
OnDestructionCallback on_destruction_callback_;
// Manages isolated CastRunners owned by |this| instance.
base::flat_set<std::unique_ptr<CastRunner>, base::UniquePtrComparator>
isolated_runners_;
DISALLOW_COPY_AND_ASSIGN(CastRunner); DISALLOW_COPY_AND_ASSIGN(CastRunner);
}; };
......
...@@ -7,9 +7,12 @@ ...@@ -7,9 +7,12 @@
#include <lib/fidl/cpp/binding.h> #include <lib/fidl/cpp/binding.h>
#include <lib/zx/channel.h> #include <lib/zx/channel.h>
#include "base/base_paths_fuchsia.h"
#include "base/callback_helpers.h"
#include "base/fuchsia/file_utils.h" #include "base/fuchsia/file_utils.h"
#include "base/fuchsia/fuchsia_logging.h" #include "base/fuchsia/fuchsia_logging.h"
#include "base/fuchsia/scoped_service_binding.h" #include "base/fuchsia/scoped_service_binding.h"
#include "base/path_service.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/test/bind_test_util.h" #include "base/test/bind_test_util.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
...@@ -175,8 +178,7 @@ class CastRunnerIntegrationTest : public testing::Test { ...@@ -175,8 +178,7 @@ class CastRunnerIntegrationTest : public testing::Test {
const uint16_t kRemoteDebuggingAnyPort = 0; const uint16_t kRemoteDebuggingAnyPort = 0;
create_context_params.set_remote_debugging_port(kRemoteDebuggingAnyPort); create_context_params.set_remote_debugging_port(kRemoteDebuggingAnyPort);
cast_runner_ = std::make_unique<CastRunner>( cast_runner_ = std::make_unique<CastRunner>(
&outgoing_directory_, &outgoing_directory_, std::move(create_context_params));
WebContentRunner::CreateWebContext(std::move(create_context_params)));
// Connect to the CastRunner's fuchsia.sys.Runner interface. // Connect to the CastRunner's fuchsia.sys.Runner interface.
fidl::InterfaceHandle<fuchsia::io::Directory> directory; fidl::InterfaceHandle<fuchsia::io::Directory> directory;
...@@ -319,7 +321,8 @@ TEST_F(CastRunnerIntegrationTest, BasicRequest) { ...@@ -319,7 +321,8 @@ TEST_F(CastRunnerIntegrationTest, BasicRequest) {
base::RunLoop run_loop; base::RunLoop run_loop;
cr_fuchsia::ResultReceiver<WebComponent*> web_component( cr_fuchsia::ResultReceiver<WebComponent*> web_component(
run_loop.QuitClosure()); run_loop.QuitClosure());
cast_runner_->GetWebComponentForTest(web_component.GetReceiveCallback()); cast_runner_->SetWebComponentCreatedCallbackForTest(
base::AdaptCallbackForRepeating(web_component.GetReceiveCallback()));
run_loop.Run(); run_loop.Run();
ASSERT_NE(*web_component, nullptr); ASSERT_NE(*web_component, nullptr);
(*web_component) (*web_component)
...@@ -405,7 +408,8 @@ TEST_F(CastRunnerIntegrationTest, IncorrectCastAppId) { ...@@ -405,7 +408,8 @@ TEST_F(CastRunnerIntegrationTest, IncorrectCastAppId) {
}); });
cr_fuchsia::ResultReceiver<WebComponent*> web_component( cr_fuchsia::ResultReceiver<WebComponent*> web_component(
run_loop.QuitClosure()); run_loop.QuitClosure());
cast_runner_->GetWebComponentForTest(web_component.GetReceiveCallback()); cast_runner_->SetWebComponentCreatedCallbackForTest(
AdaptCallbackForRepeating(web_component.GetReceiveCallback()));
run_loop.Run(); run_loop.Run();
EXPECT_FALSE(web_component.has_value()); EXPECT_FALSE(web_component.has_value());
} }
...@@ -426,8 +430,8 @@ TEST_F(CastRunnerIntegrationTest, UrlRequestRewriteRulesProvider) { ...@@ -426,8 +430,8 @@ TEST_F(CastRunnerIntegrationTest, UrlRequestRewriteRulesProvider) {
base::RunLoop run_loop; base::RunLoop run_loop;
cr_fuchsia::ResultReceiver<WebComponent*> web_component_receiver( cr_fuchsia::ResultReceiver<WebComponent*> web_component_receiver(
run_loop.QuitClosure()); run_loop.QuitClosure());
cast_runner_->GetWebComponentForTest( cast_runner_->SetWebComponentCreatedCallbackForTest(
web_component_receiver.GetReceiveCallback()); AdaptCallbackForRepeating(web_component_receiver.GetReceiveCallback()));
run_loop.Run(); run_loop.Run();
ASSERT_NE(*web_component_receiver, nullptr); ASSERT_NE(*web_component_receiver, nullptr);
web_component = *web_component_receiver; web_component = *web_component_receiver;
...@@ -534,7 +538,7 @@ TEST_F(CastRunnerIntegrationTest, RemoteDebugging) { ...@@ -534,7 +538,7 @@ TEST_F(CastRunnerIntegrationTest, RemoteDebugging) {
cr_fuchsia::ResultReceiver< cr_fuchsia::ResultReceiver<
fuchsia::web::Context_GetRemoteDebuggingPort_Result> fuchsia::web::Context_GetRemoteDebuggingPort_Result>
port_receiver(run_loop.QuitClosure()); port_receiver(run_loop.QuitClosure());
cast_runner_->context()->GetRemoteDebuggingPort( cast_runner_->GetContext()->GetRemoteDebuggingPort(
cr_fuchsia::CallbackToFitFunction(port_receiver.GetReceiveCallback())); cr_fuchsia::CallbackToFitFunction(port_receiver.GetReceiveCallback()));
run_loop.Run(); run_loop.Run();
...@@ -554,4 +558,57 @@ TEST_F(CastRunnerIntegrationTest, RemoteDebugging) { ...@@ -554,4 +558,57 @@ TEST_F(CastRunnerIntegrationTest, RemoteDebugging) {
EXPECT_EQ(devtools_url->GetString(), kBlankAppUrl.spec()); EXPECT_EQ(devtools_url->GetString(), kBlankAppUrl.spec());
} }
TEST_F(CastRunnerIntegrationTest, IsolatedContext) {
const char kBlankAppId[] = "00000000";
const GURL kContentDirectoryUrl("fuchsia-dir://testdata/echo.html");
EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 0u);
fuchsia::web::ContentDirectoryProvider provider;
provider.set_name("testdata");
base::FilePath pkg_path;
CHECK(base::PathService::Get(base::DIR_ASSETS, &pkg_path));
provider.set_directory(base::fuchsia::OpenDirectory(
pkg_path.AppendASCII("fuchsia/runners/cast/testdata")));
std::vector<fuchsia::web::ContentDirectoryProvider> providers;
providers.emplace_back(std::move(provider));
app_config_manager_.AddAppMappingWithContentDirectories(
kBlankAppId, kContentDirectoryUrl, std::move(providers));
// Launch the test-app component.
fuchsia::sys::ComponentControllerPtr component_controller =
StartCastComponent(base::StringPrintf("cast:%s", kBlankAppId));
component_controller.set_error_handler(&ComponentErrorHandler);
// Navigate to the page and verify that we read it.
{
base::RunLoop run_loop;
cr_fuchsia::ResultReceiver<WebComponent*> web_component(
run_loop.QuitClosure());
cast_runner_->SetWebComponentCreatedCallbackForTest(
AdaptCallbackForRepeating(web_component.GetReceiveCallback()));
run_loop.Run();
ASSERT_NE(*web_component, nullptr);
EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 1u);
cr_fuchsia::TestNavigationListener listener;
fidl::Binding<fuchsia::web::NavigationEventListener> listener_binding(
&listener);
(*web_component)
->frame()
->SetNavigationEventListener(listener_binding.NewBinding());
listener.RunUntilUrlAndTitleEquals(kContentDirectoryUrl, "echo");
}
// Verify that the component is torn down when |component_controller| is
// unbound.
base::RunLoop run_loop;
component_state_->set_on_delete(run_loop.QuitClosure());
component_controller.Unbind();
run_loop.Run();
EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 0u);
}
} // namespace castrunner } // namespace castrunner
...@@ -15,17 +15,14 @@ FakeApplicationConfigManager::~FakeApplicationConfigManager() = default; ...@@ -15,17 +15,14 @@ FakeApplicationConfigManager::~FakeApplicationConfigManager() = default;
void FakeApplicationConfigManager::GetConfig(std::string id, void FakeApplicationConfigManager::GetConfig(std::string id,
GetConfigCallback callback) { GetConfigCallback callback) {
const auto iter = id_to_application_config_.find(id); if (id_to_config_.find(id) == id_to_config_.end()) {
if (iter == id_to_application_config_.end()) {
LOG(ERROR) << "Unknown Cast App ID: " << id; LOG(ERROR) << "Unknown Cast App ID: " << id;
callback(chromium::cast::ApplicationConfig()); callback(chromium::cast::ApplicationConfig());
return; return;
} }
chromium::cast::ApplicationConfig app_config; callback(std::move(std::move(id_to_config_[id])));
zx_status_t status = iter->second.Clone(&app_config); id_to_config_.erase(id);
DCHECK_EQ(status, ZX_OK);
callback(std::move(app_config));
} }
void FakeApplicationConfigManager::AddAppMapping(const std::string& id, void FakeApplicationConfigManager::AddAppMapping(const std::string& id,
...@@ -36,6 +33,21 @@ void FakeApplicationConfigManager::AddAppMapping(const std::string& id, ...@@ -36,6 +33,21 @@ void FakeApplicationConfigManager::AddAppMapping(const std::string& id,
app_config.set_display_name("Dummy test app"); app_config.set_display_name("Dummy test app");
app_config.set_web_url(url.spec()); app_config.set_web_url(url.spec());
app_config.set_enable_remote_debugging(enable_remote_debugging); app_config.set_enable_remote_debugging(enable_remote_debugging);
id_to_config_[id] = std::move(app_config);
}
void FakeApplicationConfigManager::AddAppMappingWithContentDirectories(
const std::string& id,
const GURL& url,
std::vector<fuchsia::web::ContentDirectoryProvider> directories) {
chromium::cast::ApplicationConfig app_config;
app_config.set_id(id);
app_config.set_display_name("Dummy test app");
app_config.set_web_url(url.spec());
if (!directories.empty()) {
app_config.set_content_directories_for_isolated_application(
std::move(directories));
}
id_to_application_config_[id] = std::move(app_config); id_to_config_[id] = std::move(app_config);
} }
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "fuchsia/fidl/chromium/cast/cpp/fidl.h" #include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
...@@ -26,12 +27,18 @@ class FakeApplicationConfigManager ...@@ -26,12 +27,18 @@ class FakeApplicationConfigManager
const GURL& url, const GURL& url,
bool enable_remote_debugging); bool enable_remote_debugging);
// Associates a Cast application |id| with a url and a set of content
// directories, to be served from the EmbeddedTestServer.
void AddAppMappingWithContentDirectories(
const std::string& id,
const GURL& url,
std::vector<fuchsia::web::ContentDirectoryProvider> directories);
// chromium::cast::ApplicationConfigManager interface. // chromium::cast::ApplicationConfigManager interface.
void GetConfig(std::string id, GetConfigCallback config_callback) override; void GetConfig(std::string id, GetConfigCallback config_callback) override;
private: private:
std::map<std::string, chromium::cast::ApplicationConfig> std::map<std::string, chromium::cast::ApplicationConfig> id_to_config_;
id_to_application_config_;
DISALLOW_COPY_AND_ASSIGN(FakeApplicationConfigManager); DISALLOW_COPY_AND_ASSIGN(FakeApplicationConfigManager);
}; };
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// 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 <fuchsia/sys/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h> #include <lib/sys/cpp/component_context.h>
#include "base/command_line.h" #include "base/command_line.h"
...@@ -51,7 +50,7 @@ int main(int argc, char** argv) { ...@@ -51,7 +50,7 @@ int main(int argc, char** argv) {
CastRunner runner( CastRunner runner(
base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get(), base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get(),
WebContentRunner::CreateWebContext(std::move(create_context_params))); std::move(create_context_params));
base::fuchsia::ComponentContextForCurrentProcess() base::fuchsia::ComponentContextForCurrentProcess()
->outgoing() ->outgoing()
......
...@@ -65,8 +65,8 @@ void WebComponent::StartComponent() { ...@@ -65,8 +65,8 @@ void WebComponent::StartComponent() {
// Create the underlying Frame and get its NavigationController. // Create the underlying Frame and get its NavigationController.
fuchsia::web::CreateFrameParams create_params; fuchsia::web::CreateFrameParams create_params;
create_params.set_enable_remote_debugging(enable_remote_debugging_); create_params.set_enable_remote_debugging(enable_remote_debugging_);
runner_->context()->CreateFrameWithParams(std::move(create_params), runner_->GetContext()->CreateFrameWithParams(std::move(create_params),
frame_.NewRequest()); frame_.NewRequest());
// If the Frame unexpectedly disconnect us then tear-down this Component. // If the Frame unexpectedly disconnect us then tear-down this Component.
frame_.set_error_handler([this](zx_status_t status) { frame_.set_error_handler([this](zx_status_t status) {
...@@ -93,7 +93,6 @@ void WebComponent::StartComponent() { ...@@ -93,7 +93,6 @@ void WebComponent::StartComponent() {
void WebComponent::LoadUrl( void WebComponent::LoadUrl(
const GURL& url, const GURL& url,
std::vector<fuchsia::net::http::Header> extra_headers) { std::vector<fuchsia::net::http::Header> extra_headers) {
DCHECK(component_started_);
DCHECK(url.is_valid()); DCHECK(url.is_valid());
fuchsia::web::NavigationControllerPtr navigation_controller; fuchsia::web::NavigationControllerPtr navigation_controller;
frame()->GetNavigationController(navigation_controller.NewRequest()); frame()->GetNavigationController(navigation_controller.NewRequest());
......
...@@ -76,14 +76,29 @@ fuchsia::web::CreateContextParams WebContentRunner::BuildCreateContextParams( ...@@ -76,14 +76,29 @@ fuchsia::web::CreateContextParams WebContentRunner::BuildCreateContextParams(
return create_params; return create_params;
} }
WebContentRunner::WebContentRunner(sys::OutgoingDirectory* outgoing_directory, WebContentRunner::WebContentRunner(
fuchsia::web::ContextPtr context) sys::OutgoingDirectory* outgoing_directory,
: context_(std::move(context)), service_binding_(outgoing_directory, this) { CreateContextCallback create_context_callback)
DCHECK(context_); : create_context_callback_(std::move(create_context_callback)) {
DCHECK(create_context_callback_);
service_binding_.emplace(outgoing_directory, this);
} }
WebContentRunner::WebContentRunner(fuchsia::web::ContextPtr context)
: context_(std::move(context)) {}
WebContentRunner::~WebContentRunner() = default; WebContentRunner::~WebContentRunner() = default;
fuchsia::web::Context* WebContentRunner::GetContext() {
if (!context_) {
DCHECK(create_context_callback_);
context_ = std::move(create_context_callback_).Run();
DCHECK(context_);
}
return context_.get();
}
void WebContentRunner::StartComponent( void WebContentRunner::StartComponent(
fuchsia::sys::Package package, fuchsia::sys::Package package,
fuchsia::sys::StartupInfo startup_info, fuchsia::sys::StartupInfo startup_info,
...@@ -104,13 +119,10 @@ void WebContentRunner::StartComponent( ...@@ -104,13 +119,10 @@ void WebContentRunner::StartComponent(
RegisterComponent(std::move(component)); RegisterComponent(std::move(component));
} }
void WebContentRunner::GetWebComponentForTest( void WebContentRunner::SetWebComponentCreatedCallbackForTest(
base::OnceCallback<void(WebComponent*)> callback) { base::RepeatingCallback<void(WebComponent*)> callback) {
if (!components_.empty()) { DCHECK(components_.empty());
std::move(callback).Run(components_.begin()->get()); web_component_created_callback_for_test_ = std::move(callback);
return;
}
web_component_test_callback_ = std::move(callback);
} }
void WebContentRunner::DestroyComponent(WebComponent* component) { void WebContentRunner::DestroyComponent(WebComponent* component) {
...@@ -119,8 +131,8 @@ void WebContentRunner::DestroyComponent(WebComponent* component) { ...@@ -119,8 +131,8 @@ void WebContentRunner::DestroyComponent(WebComponent* component) {
void WebContentRunner::RegisterComponent( void WebContentRunner::RegisterComponent(
std::unique_ptr<WebComponent> component) { std::unique_ptr<WebComponent> component) {
if (web_component_test_callback_) { if (web_component_created_callback_for_test_)
std::move(web_component_test_callback_).Run(component.get()); web_component_created_callback_for_test_.Run(component.get());
}
components_.insert(std::move(component)); components_.insert(std::move(component));
} }
...@@ -9,17 +9,21 @@ ...@@ -9,17 +9,21 @@
#include <fuchsia/web/cpp/fidl.h> #include <fuchsia/web/cpp/fidl.h>
#include <memory> #include <memory>
#include <set> #include <set>
#include <vector>
#include "base/callback.h" #include "base/callback.h"
#include "base/containers/unique_ptr_adapters.h" #include "base/containers/unique_ptr_adapters.h"
#include "base/fuchsia/scoped_service_binding.h" #include "base/fuchsia/scoped_service_binding.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h"
class WebComponent; class WebComponent;
// sys::Runner that instantiates components hosting standard web content. // sys::Runner that instantiates components hosting standard web content.
class WebContentRunner : public fuchsia::sys::Runner { class WebContentRunner : public fuchsia::sys::Runner {
public: public:
using CreateContextCallback = base::OnceCallback<fuchsia::web::ContextPtr()>;
// Creates and returns a web.Context with a default path and parameters, // Creates and returns a web.Context with a default path and parameters,
// and with access to the same services as this Runner. The returned binding // and with access to the same services as this Runner. The returned binding
// is configured to exit this process on error. // is configured to exit this process on error.
...@@ -42,17 +46,23 @@ class WebContentRunner : public fuchsia::sys::Runner { ...@@ -42,17 +46,23 @@ class WebContentRunner : public fuchsia::sys::Runner {
// published. |on_idle_closure| will be invoked when the final client of the // published. |on_idle_closure| will be invoked when the final client of the
// published service disconnects, even if one or more Components are still // published service disconnects, even if one or more Components are still
// active. // active.
// |context|: Context (e.g. persisted profile storage) under which all web // |create_context_callback|: A callback that, when invoked, connects a
// content launched through this Runner instance will be run. // fuchsia.web.Context under which all web content launched through this
// Runner instance will be run.
WebContentRunner(sys::OutgoingDirectory* outgoing_directory, WebContentRunner(sys::OutgoingDirectory* outgoing_directory,
fuchsia::web::ContextPtr context); CreateContextCallback create_context_callback);
// Alternative constructor for unpublished Runners.
explicit WebContentRunner(fuchsia::web::ContextPtr context);
~WebContentRunner() override; ~WebContentRunner() override;
fuchsia::web::Context* context() { return context_.get(); } // Gets a pointer to this runner's Context, creating one if needed.
fuchsia::web::Context* GetContext();
// Used by WebComponent instances to signal that the ComponentController // Used by WebComponent instances to signal that the ComponentController
// channel was dropped, and therefore the component should be destroyed. // channel was dropped, and therefore the component should be destroyed.
void DestroyComponent(WebComponent* component); virtual void DestroyComponent(WebComponent* component);
// fuchsia::sys::Runner implementation. // fuchsia::sys::Runner implementation.
void StartComponent(fuchsia::sys::Package package, void StartComponent(fuchsia::sys::Package package,
...@@ -61,22 +71,33 @@ class WebContentRunner : public fuchsia::sys::Runner { ...@@ -61,22 +71,33 @@ class WebContentRunner : public fuchsia::sys::Runner {
controller_request) override; controller_request) override;
// Used by tests to asynchronously access the first WebComponent. // Used by tests to asynchronously access the first WebComponent.
void GetWebComponentForTest(base::OnceCallback<void(WebComponent*)> callback); void SetWebComponentCreatedCallbackForTest(
base::RepeatingCallback<void(WebComponent*)> callback);
protected:
// Registers a WebComponent, or specialization, with this Runner. // Registers a WebComponent, or specialization, with this Runner.
void RegisterComponent(std::unique_ptr<WebComponent> component); void RegisterComponent(std::unique_ptr<WebComponent> component);
protected:
base::RepeatingCallback<void(WebComponent*)>
web_component_created_callback_for_test() const {
return web_component_created_callback_for_test_;
}
private: private:
// If set, invoked whenever a WebComponent is created.
base::RepeatingCallback<void(WebComponent*)>
web_component_created_callback_for_test_;
CreateContextCallback create_context_callback_;
fuchsia::web::ContextPtr context_; fuchsia::web::ContextPtr context_;
std::set<std::unique_ptr<WebComponent>, base::UniquePtrComparator> std::set<std::unique_ptr<WebComponent>, base::UniquePtrComparator>
components_; components_;
// Publishes this Runner into the service directory specified at construction. // Publishes this Runner into the service directory specified at construction.
base::fuchsia::ScopedServiceBinding<fuchsia::sys::Runner> service_binding_; // This is not set for child runner instances.
base::Optional<base::fuchsia::ScopedServiceBinding<fuchsia::sys::Runner>>
// Test-only callback for GetWebComponentForTest. service_binding_;
base::OnceCallback<void(WebComponent*)> web_component_test_callback_;
DISALLOW_COPY_AND_ASSIGN(WebContentRunner); DISALLOW_COPY_AND_ASSIGN(WebContentRunner);
}; };
......
...@@ -31,7 +31,8 @@ int main(int argc, char** argv) { ...@@ -31,7 +31,8 @@ int main(int argc, char** argv) {
WebContentRunner runner( WebContentRunner runner(
base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get(), base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get(),
WebContentRunner::CreateDefaultWebContext(kWebRunnerFeatures)); base::BindOnce(&WebContentRunner::CreateDefaultWebContext,
kWebRunnerFeatures));
base::fuchsia::ComponentContextForCurrentProcess() base::fuchsia::ComponentContextForCurrentProcess()
->outgoing() ->outgoing()
......
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