summaryrefslogtreecommitdiff
path: root/chromium/fuchsia/runners
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/fuchsia/runners
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/fuchsia/runners')
-rw-r--r--chromium/fuchsia/runners/BUILD.gn25
-rw-r--r--chromium/fuchsia/runners/cast/OWNERS2
-rw-r--r--chromium/fuchsia/runners/cast/api_bindings_client.cc34
-rw-r--r--chromium/fuchsia/runners/cast/api_bindings_client.h19
-rw-r--r--chromium/fuchsia/runners/cast/application_controller_impl.cc6
-rw-r--r--chromium/fuchsia/runners/cast/application_controller_impl.h5
-rw-r--r--chromium/fuchsia/runners/cast/application_controller_impl_unittest.cc13
-rw-r--r--chromium/fuchsia/runners/cast/cast_component.cc74
-rw-r--r--chromium/fuchsia/runners/cast/cast_component.h13
-rw-r--r--chromium/fuchsia/runners/cast/cast_runner.cc108
-rw-r--r--chromium/fuchsia/runners/cast/cast_runner.cmx1
-rw-r--r--chromium/fuchsia/runners/cast/cast_runner.h19
-rw-r--r--chromium/fuchsia/runners/cast/cast_runner_integration_test.cc129
-rw-r--r--chromium/fuchsia/runners/cast/cast_streaming.cc66
-rw-r--r--chromium/fuchsia/runners/cast/cast_streaming.h33
-rw-r--r--chromium/fuchsia/runners/cast/data/receiver.html36
-rw-r--r--chromium/fuchsia/runners/cast/main.cc21
-rw-r--r--chromium/fuchsia/runners/cast/named_message_port_connector.cc1
-rw-r--r--chromium/fuchsia/runners/cast/pending_cast_component.cc2
-rw-r--r--chromium/fuchsia/runners/common/web_component.cc68
-rw-r--r--chromium/fuchsia/runners/common/web_component.h39
-rw-r--r--chromium/fuchsia/runners/common/web_content_runner.cc4
-rw-r--r--chromium/fuchsia/runners/web/OWNERS2
-rw-r--r--chromium/fuchsia/runners/web/main.cc13
-rw-r--r--chromium/fuchsia/runners/web/web_runner_smoke_test.cc10
25 files changed, 582 insertions, 161 deletions
diff --git a/chromium/fuchsia/runners/BUILD.gn b/chromium/fuchsia/runners/BUILD.gn
index 72d04361911..4b1a7c74646 100644
--- a/chromium/fuchsia/runners/BUILD.gn
+++ b/chromium/fuchsia/runners/BUILD.gn
@@ -7,7 +7,6 @@ assert(is_fuchsia)
import("//build/buildflag_header.gni")
import("//build/config/fuchsia/generate_runner_scripts.gni")
import("//build/config/fuchsia/symbol_archive.gni")
-import("//fuchsia/release_channel.gni")
import("//testing/test.gni")
declare_args() {
@@ -15,9 +14,6 @@ declare_args() {
web_runner_remote_debugging_port = 0
}
-_cast_runner_package_name = "cast_runner${release_channel_suffix}"
-_web_runner_package_name = "web_runner${release_channel_suffix}"
-
buildflag_header("buildflags") {
header = "buildflags.h"
flags =
@@ -38,6 +34,7 @@ source_set("common") {
"//base",
"//fuchsia/base",
"//fuchsia/base:modular",
+ "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp",
"//ui/gfx/geometry",
"//url",
]
@@ -63,17 +60,21 @@ source_set("cast_runner_core") {
"cast/cast_component.h",
"cast/cast_runner.cc",
"cast/cast_runner.h",
+ "cast/cast_streaming.cc",
+ "cast/cast_streaming.h",
"cast/named_message_port_connector.cc",
"cast/named_message_port_connector.h",
"cast/pending_cast_component.cc",
"cast/pending_cast_component.h",
]
data_deps = [ "//chromecast/bindings:named_message_port_connector_resources" ]
+ data = [ "cast/data" ]
deps = [
"//base",
"//fuchsia/base",
"//fuchsia/base:modular",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.modular",
+ "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp",
"//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
"//url",
]
@@ -100,19 +101,17 @@ executable("cast_runner_exe") {
cr_fuchsia_package("cast_runner_pkg") {
binary = ":cast_runner_exe"
- package_name_override = _cast_runner_package_name
- archive_name_override = "cast_runner"
- component_name_override = "cast_runner"
+ package_name_override = "cast_runner"
manifest = "cast/cast_runner.cmx"
}
fuchsia_package_runner("cast_runner") {
package = ":cast_runner_pkg"
- archive_name_override = "cast_runner"
+ package_name_override = "cast_runner"
install_only = true
package_deps = [ [
"//fuchsia/engine:web_engine",
- "web_engine${release_channel_suffix}",
+ "web_engine",
] ]
}
@@ -208,19 +207,17 @@ executable("web_runner_exe") {
cr_fuchsia_package("web_runner_pkg") {
binary = ":web_runner_exe"
- package_name_override = _web_runner_package_name
- component_name_override = "web_runner"
- archive_name_override = "web_runner"
+ package_name_override = "web_runner"
manifest = "web/web_runner.cmx"
}
fuchsia_package_runner("web_runner") {
package = ":web_runner_pkg"
- archive_name_override = "web_runner"
+ package_name_override = "web_runner"
install_only = true
package_deps = [ [
"//fuchsia/engine:web_engine",
- "web_engine${release_channel_suffix}",
+ "web_engine",
] ]
}
diff --git a/chromium/fuchsia/runners/cast/OWNERS b/chromium/fuchsia/runners/cast/OWNERS
new file mode 100644
index 00000000000..2f43650c9db
--- /dev/null
+++ b/chromium/fuchsia/runners/cast/OWNERS
@@ -0,0 +1,2 @@
+per-file *.cmx=set noparent
+per-file *.cmx=file://fuchsia/SECURITY_OWNERS
diff --git a/chromium/fuchsia/runners/cast/api_bindings_client.cc b/chromium/fuchsia/runners/cast/api_bindings_client.cc
index 153c76b10f1..9cd338c6d42 100644
--- a/chromium/fuchsia/runners/cast/api_bindings_client.cc
+++ b/chromium/fuchsia/runners/cast/api_bindings_client.cc
@@ -33,11 +33,14 @@ ApiBindingsClient::ApiBindingsClient(
});
}
-void ApiBindingsClient::OnBindingsReceived(
- std::vector<chromium::cast::ApiBinding> bindings) {
- bindings_ = std::move(bindings);
- bindings_service_.set_error_handler(nullptr);
- std::move(on_initialization_complete_).Run();
+ApiBindingsClient::~ApiBindingsClient() {
+ if (connector_ && frame_) {
+ connector_->Register({});
+
+ // Remove all injected scripts using their automatically enumerated IDs.
+ for (uint64_t i = 0; i < bindings_->size(); ++i)
+ frame_->RemoveBeforeLoadJavaScript(kBindingsIdStart + i);
+ }
}
void ApiBindingsClient::AttachToFrame(fuchsia::web::Frame* frame,
@@ -74,14 +77,14 @@ void ApiBindingsClient::AttachToFrame(fuchsia::web::Frame* frame,
}
}
-ApiBindingsClient::~ApiBindingsClient() {
- if (connector_ && frame_) {
- connector_->Register({});
+void ApiBindingsClient::DetachFromFrame(fuchsia::web::Frame* frame) {
+ DCHECK_EQ(frame, frame_);
+ frame_ = nullptr;
+ bindings_service_.set_error_handler(nullptr);
+}
- // Remove all injected scripts using their automatically enumerated IDs.
- for (uint64_t i = 0; i < bindings_->size(); ++i)
- frame_->RemoveBeforeLoadJavaScript(kBindingsIdStart + i);
- }
+bool ApiBindingsClient::HasBindings() const {
+ return bindings_.has_value();
}
void ApiBindingsClient::OnPortConnected(
@@ -91,6 +94,9 @@ void ApiBindingsClient::OnPortConnected(
bindings_service_->Connect(port_name.as_string(), std::move(port));
}
-bool ApiBindingsClient::HasBindings() const {
- return bindings_.has_value();
+void ApiBindingsClient::OnBindingsReceived(
+ std::vector<chromium::cast::ApiBinding> bindings) {
+ bindings_ = std::move(bindings);
+ bindings_service_.set_error_handler(nullptr);
+ std::move(on_initialization_complete_).Run();
}
diff --git a/chromium/fuchsia/runners/cast/api_bindings_client.h b/chromium/fuchsia/runners/cast/api_bindings_client.h
index 8cb11926837..219e419e312 100644
--- a/chromium/fuchsia/runners/cast/api_bindings_client.h
+++ b/chromium/fuchsia/runners/cast/api_bindings_client.h
@@ -27,24 +27,31 @@ class ApiBindingsClient {
~ApiBindingsClient();
// Injects APIs and handles channel connections on |frame|.
- // |on_error_closure|: Invoked in the event of an unrecoverable error (e.g.
- // lost connection to the Agent). The callback must
- // remain valid for the entire lifetime of |this|.
+ // |on_error_callback| is invoked in the event of an unrecoverable error (e.g.
+ // lost connection to the Agent). The callback must remain valid for the
+ // entire lifetime of |this|.
void AttachToFrame(fuchsia::web::Frame* frame,
NamedMessagePortConnector* connector,
base::OnceClosure on_error_callback);
+ // Indicates that the Frame is no longer live, preventing the API bindings
+ // client from attempting to remove injected bindings from it.
+ void DetachFromFrame(fuchsia::web::Frame* frame);
+
// Indicates that bindings were successfully received from
// |bindings_service_|.
bool HasBindings() const;
+ // TODO(crbug.com/1082821): Move this method back to private once the Cast
+ // Streaming Receiver component has been implemented.
+ // Called when |connector_| has connected a port.
+ void OnPortConnected(base::StringPiece port_name,
+ fidl::InterfaceHandle<fuchsia::web::MessagePort> port);
+
private:
// Called when ApiBindings::GetAll() has responded.
void OnBindingsReceived(std::vector<chromium::cast::ApiBinding> bindings);
- // Called when |connector_| has connected a port.
- void OnPortConnected(base::StringPiece port_name,
- fidl::InterfaceHandle<fuchsia::web::MessagePort> port);
base::Optional<std::vector<chromium::cast::ApiBinding>> bindings_;
fuchsia::web::Frame* frame_ = nullptr;
diff --git a/chromium/fuchsia/runners/cast/application_controller_impl.cc b/chromium/fuchsia/runners/cast/application_controller_impl.cc
index 48d0327db6a..642eacabee2 100644
--- a/chromium/fuchsia/runners/cast/application_controller_impl.cc
+++ b/chromium/fuchsia/runners/cast/application_controller_impl.cc
@@ -6,17 +6,17 @@
#include <utility>
+#include "base/check.h"
#include "base/fuchsia/fuchsia_logging.h"
-#include "base/logging.h"
ApplicationControllerImpl::ApplicationControllerImpl(
fuchsia::web::Frame* frame,
- fidl::InterfaceHandle<chromium::cast::ApplicationContext> context)
+ chromium::cast::ApplicationContext* context)
: binding_(this), frame_(frame) {
DCHECK(context);
DCHECK(frame_);
- context.Bind()->SetApplicationController(binding_.NewBinding());
+ context->SetApplicationController(binding_.NewBinding());
binding_.set_error_handler([](zx_status_t status) {
if (status != ZX_ERR_PEER_CLOSED && status != ZX_ERR_CANCELED) {
diff --git a/chromium/fuchsia/runners/cast/application_controller_impl.h b/chromium/fuchsia/runners/cast/application_controller_impl.h
index ae77a875022..193c1e80e45 100644
--- a/chromium/fuchsia/runners/cast/application_controller_impl.h
+++ b/chromium/fuchsia/runners/cast/application_controller_impl.h
@@ -15,9 +15,8 @@
class ApplicationControllerImpl : public chromium::cast::ApplicationController {
public:
- ApplicationControllerImpl(
- fuchsia::web::Frame* frame,
- fidl::InterfaceHandle<chromium::cast::ApplicationContext> context);
+ ApplicationControllerImpl(fuchsia::web::Frame* frame,
+ chromium::cast::ApplicationContext* context);
~ApplicationControllerImpl() final;
protected:
diff --git a/chromium/fuchsia/runners/cast/application_controller_impl_unittest.cc b/chromium/fuchsia/runners/cast/application_controller_impl_unittest.cc
index 46d85770919..624787c3fe4 100644
--- a/chromium/fuchsia/runners/cast/application_controller_impl_unittest.cc
+++ b/chromium/fuchsia/runners/cast/application_controller_impl_unittest.cc
@@ -41,8 +41,9 @@ class ApplicationControllerImplTest : public chromium::cast::ApplicationContext,
public testing::Test {
public:
ApplicationControllerImplTest()
- : application_context_(this),
- application_(&frame_, application_context_.NewBinding()) {
+ : application_context_binding_(this),
+ application_context_(application_context_binding_.NewBinding().Bind()),
+ application_(&frame_, application_context_.get()) {
base::RunLoop run_loop;
wait_for_controller_callback_ = run_loop.QuitClosure();
run_loop.Run();
@@ -51,7 +52,7 @@ class ApplicationControllerImplTest : public chromium::cast::ApplicationContext,
~ApplicationControllerImplTest() override = default;
protected:
- // chromium::cast::ApplicationReceiver implementation.
+ // chromium::cast::ApplicationContext implementation.
void GetMediaSessionId(GetMediaSessionIdCallback callback) final {
NOTREACHED();
}
@@ -68,10 +69,12 @@ class ApplicationControllerImplTest : public chromium::cast::ApplicationContext,
base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
MockFrame frame_;
- fidl::Binding<chromium::cast::ApplicationContext> application_context_;
+ fidl::Binding<chromium::cast::ApplicationContext>
+ application_context_binding_;
+ chromium::cast::ApplicationContextPtr application_context_;
+ ApplicationControllerImpl application_;
chromium::cast::ApplicationControllerPtr application_ptr_;
- ApplicationControllerImpl application_;
base::OnceClosure wait_for_controller_callback_;
private:
diff --git a/chromium/fuchsia/runners/cast/cast_component.cc b/chromium/fuchsia/runners/cast/cast_component.cc
index 8a3c24c90b5..863de881129 100644
--- a/chromium/fuchsia/runners/cast/cast_component.cc
+++ b/chromium/fuchsia/runners/cast/cast_component.cc
@@ -5,6 +5,7 @@
#include "fuchsia/runners/cast/cast_component.h"
#include <lib/fidl/cpp/binding.h>
+#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <algorithm>
#include <utility>
@@ -18,6 +19,7 @@
#include "fuchsia/base/mem_buffer_util.h"
#include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
#include "fuchsia/runners/cast/cast_runner.h"
+#include "fuchsia/runners/cast/cast_streaming.h"
#include "fuchsia/runners/common/web_component.h"
namespace {
@@ -56,9 +58,9 @@ CastComponent::CastComponent(WebContentRunner* runner,
initial_url_rewrite_rules_(
std::move(params.initial_url_rewrite_rules.value())),
api_bindings_client_(std::move(params.api_bindings_client)),
+ application_context_(params.application_context.Bind()),
media_session_id_(params.media_session_id.value()),
- headless_disconnect_watch_(FROM_HERE),
- navigation_listener_binding_(this) {
+ headless_disconnect_watch_(FROM_HERE) {
base::AutoReset<bool> constructor_active_reset(&constructor_active_, true);
}
@@ -89,8 +91,34 @@ void CastComponent::StartComponent() {
frame()->SetMediaSessionId(media_session_id_);
frame()->ConfigureInputTypes(fuchsia::web::InputTypes::ALL,
fuchsia::web::AllowInputState::DENY);
- frame()->SetNavigationEventListener(
- navigation_listener_binding_.NewBinding());
+ frame()->SetJavaScriptLogLevel(fuchsia::web::ConsoleLogLevel::WARN);
+
+ if (IsAppConfigForCastStreaming(application_config_)) {
+ // TODO(crbug.com/1082821): Remove this once the Cast Streaming Receiver
+ // component has been implemented.
+
+ // Register the MessagePort for the Cast Streaming Receiver.
+ fidl::InterfaceHandle<fuchsia::web::MessagePort> message_port;
+ fuchsia::web::WebMessage message;
+ message.set_data(cr_fuchsia::MemBufferFromString("", "empty_message"));
+ fuchsia::web::OutgoingTransferable outgoing_transferable;
+ outgoing_transferable.set_message_port(message_port.NewRequest());
+ std::vector<fuchsia::web::OutgoingTransferable> outgoing_transferables;
+ outgoing_transferables.push_back(std::move(outgoing_transferable));
+ message.set_outgoing_transfer(std::move(outgoing_transferables));
+
+ frame()->PostMessage(
+ kCastStreamingMessagePortOrigin, std::move(message),
+ [this](fuchsia::web::Frame_PostMessage_Result result) {
+ if (result.is_err()) {
+ DestroyComponent(kBindingsFailureExitCode,
+ fuchsia::sys::TerminationReason::INTERNAL_ERROR);
+ }
+ });
+ api_bindings_client_->OnPortConnected(kCastStreamingMessagePortName,
+ std::move(message_port));
+ }
+
api_bindings_client_->AttachToFrame(
frame(), connector_.get(),
base::BindOnce(&CastComponent::DestroyComponent, base::Unretained(this),
@@ -107,13 +135,11 @@ void CastComponent::StartComponent() {
}
application_controller_ = std::make_unique<ApplicationControllerImpl>(
- frame(),
- agent_manager_->ConnectToAgentService<chromium::cast::ApplicationContext>(
- application_config_.agent_url()));
+ frame(), application_context_.get());
// Pass application permissions to the frame.
- std::string origin = GURL(application_config_.web_url()).GetOrigin().spec();
if (application_config_.has_permissions()) {
+ std::string origin = GURL(application_config_.web_url()).GetOrigin().spec();
for (auto& permission : application_config_.permissions()) {
fuchsia::web::PermissionDescriptor permission_clone;
zx_status_t status = permission.Clone(&permission_clone);
@@ -124,13 +150,24 @@ void CastComponent::StartComponent() {
}
}
-void CastComponent::DestroyComponent(int termination_exit_code,
+void CastComponent::DestroyComponent(int64_t exit_code,
fuchsia::sys::TerminationReason reason) {
DCHECK(!constructor_active_);
std::move(on_destroyed_).Run();
- WebComponent::DestroyComponent(termination_exit_code, reason);
+ // If the component EXITED then pass the |exit_code| to the Agent, to allow it
+ // to distinguish graceful termination from crashes.
+ if (reason == fuchsia::sys::TerminationReason::EXITED &&
+ application_controller_) {
+ application_context_->OnApplicationExit(exit_code);
+ }
+
+ // frame() is about to be destroyed, so there is no need to perform cleanup
+ // such as removing before-load JavaScripts.
+ api_bindings_client_->DetachFromFrame(frame());
+
+ WebComponent::DestroyComponent(exit_code, reason);
}
void CastComponent::OnRewriteRulesReceived(
@@ -146,13 +183,24 @@ void CastComponent::OnNavigationStateChanged(
OnNavigationStateChangedCallback callback) {
if (change.has_is_main_document_loaded() && change.is_main_document_loaded())
connector_->OnPageLoad();
- callback();
+ WebComponent::OnNavigationStateChanged(std::move(change),
+ std::move(callback));
}
void CastComponent::CreateView(
zx::eventpair view_token,
fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services,
fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services) {
+ scenic::ViewRefPair view_ref_pair = scenic::ViewRefPair::New();
+ CreateViewWithViewRef(std::move(view_token),
+ std::move(view_ref_pair.control_ref),
+ std::move(view_ref_pair.view_ref));
+}
+
+void CastComponent::CreateViewWithViewRef(
+ zx::eventpair view_token,
+ fuchsia::ui::views::ViewRefControl control_ref,
+ fuchsia::ui::views::ViewRef view_ref) {
if (is_headless_) {
// For headless CastComponents, |view_token| does not actually connect to a
// Scenic View. It is merely used as a conduit for propagating termination
@@ -166,8 +214,8 @@ void CastComponent::CreateView(
return;
}
- WebComponent::CreateView(std::move(view_token), std::move(incoming_services),
- std::move(outgoing_services));
+ WebComponent::CreateViewWithViewRef(
+ std::move(view_token), std::move(control_ref), std::move(view_ref));
}
void CastComponent::OnZxHandleSignalled(zx_handle_t handle,
diff --git a/chromium/fuchsia/runners/cast/cast_component.h b/chromium/fuchsia/runners/cast/cast_component.h
index 2d0516deeca..b1589330797 100644
--- a/chromium/fuchsia/runners/cast/cast_component.h
+++ b/chromium/fuchsia/runners/cast/cast_component.h
@@ -14,6 +14,7 @@
#include "base/message_loop/message_pump_for_io.h"
#include "base/message_loop/message_pump_fuchsia.h"
#include "base/optional.h"
+#include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
#include "fuchsia/runners/cast/api_bindings_client.h"
#include "fuchsia/runners/cast/application_controller_impl.h"
#include "fuchsia/runners/cast/named_message_port_connector.h"
@@ -27,7 +28,6 @@ FORWARD_DECLARE_TEST(HeadlessCastRunnerIntegrationTest, Headless);
// A specialization of WebComponent which adds Cast-specific services.
class CastComponent : public WebComponent,
- public fuchsia::web::NavigationEventListener,
public base::MessagePumpFuchsia::ZxHandleWatcher {
public:
struct Params {
@@ -52,6 +52,8 @@ class CastComponent : public WebComponent,
// Parameters asynchronously initialized by PendingCastComponent.
std::unique_ptr<ApiBindingsClient> api_bindings_client;
chromium::cast::ApplicationConfig application_config;
+ fidl::InterfaceHandle<chromium::cast::ApplicationContext>
+ application_context;
base::Optional<std::vector<fuchsia::web::UrlRequestRewriteRule>>
initial_url_rewrite_rules;
base::Optional<uint64_t> media_session_id;
@@ -64,7 +66,7 @@ class CastComponent : public WebComponent,
// WebComponent overrides.
void StartComponent() final;
- void DestroyComponent(int termination_exit_code,
+ void DestroyComponent(int64_t termination_exit_code,
fuchsia::sys::TerminationReason reason) final;
const chromium::cast::ApplicationConfig& application_config() {
@@ -89,6 +91,9 @@ class CastComponent : public WebComponent,
fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services,
fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services)
final;
+ void CreateViewWithViewRef(zx::eventpair view_token,
+ fuchsia::ui::views::ViewRefControl control_ref,
+ fuchsia::ui::views::ViewRef view_ref) final;
// base::MessagePumpFuchsia::ZxHandleWatcher implementation.
// Called when the headless "view" token is disconnected.
@@ -106,13 +111,11 @@ class CastComponent : public WebComponent,
std::unique_ptr<NamedMessagePortConnector> connector_;
std::unique_ptr<ApiBindingsClient> api_bindings_client_;
std::unique_ptr<ApplicationControllerImpl> application_controller_;
+ chromium::cast::ApplicationContextPtr application_context_;
uint64_t media_session_id_ = 0;
zx::eventpair headless_view_token_;
base::MessagePumpForIO::ZxHandleWatchController headless_disconnect_watch_;
- fidl::Binding<fuchsia::web::NavigationEventListener>
- navigation_listener_binding_;
-
DISALLOW_COPY_AND_ASSIGN(CastComponent);
};
diff --git a/chromium/fuchsia/runners/cast/cast_runner.cc b/chromium/fuchsia/runners/cast/cast_runner.cc
index 26f30af3870..a35875b941c 100644
--- a/chromium/fuchsia/runners/cast/cast_runner.cc
+++ b/chromium/fuchsia/runners/cast/cast_runner.cc
@@ -15,8 +15,10 @@
#include "base/fuchsia/file_utils.h"
#include "base/fuchsia/filtered_service_directory.h"
#include "base/fuchsia/fuchsia_logging.h"
+#include "base/fuchsia/process_context.h"
#include "base/logging.h"
#include "fuchsia/base/agent_manager.h"
+#include "fuchsia/runners/cast/cast_streaming.h"
#include "fuchsia/runners/cast/pending_cast_component.h"
#include "fuchsia/runners/common/web_content_runner.h"
#include "url/gurl.h"
@@ -69,15 +71,13 @@ bool IsPermissionGrantedInAppConfig(
CastRunner::CastRunner(bool is_headless)
: is_headless_(is_headless),
main_services_(std::make_unique<base::fuchsia::FilteredServiceDirectory>(
- base::fuchsia::ComponentContextForCurrentProcess()->svc().get())),
+ base::ComponentContextForProcess()->svc().get())),
main_context_(std::make_unique<WebContentRunner>(
base::BindRepeating(&CastRunner::GetMainContextParams,
base::Unretained(this)))),
isolated_services_(
std::make_unique<base::fuchsia::FilteredServiceDirectory>(
- base::fuchsia::ComponentContextForCurrentProcess()
- ->svc()
- .get())) {
+ base::ComponentContextForProcess()->svc().get())) {
// Specify the services to connect via the Runner process' service directory.
for (const char* name : kServices) {
main_services_->AddService(name);
@@ -132,40 +132,38 @@ void CastRunner::SetOnMainContextLostCallbackForTest(
void CastRunner::LaunchPendingComponent(PendingCastComponent* pending_component,
CastComponent::Params params) {
- WebContentRunner* component_owner = main_context_.get();
-
// Save the list of CORS exemptions so that they can be used in Context
// creation parameters.
cors_exempt_headers_ = pending_component->TakeCorsExemptHeaders();
- const bool is_isolated =
- params.application_config
- .has_content_directories_for_isolated_application();
- if (is_isolated) {
- // Create an isolated context which will own the CastComponent.
- auto context =
- std::make_unique<WebContentRunner>(GetIsolatedContextParams(std::move(
- *params.application_config
- .mutable_content_directories_for_isolated_application())));
- context->SetOnEmptyCallback(base::BindOnce(
- &CastRunner::OnIsolatedContextEmpty, base::Unretained(this),
- base::Unretained(context.get())));
- component_owner = context.get();
- isolated_contexts_.insert(std::move(context));
+ // TODO(crbug.com/1082821): Remove |web_content_url| once the Cast Streaming
+ // Receiver component has been implemented.
+ GURL web_content_url(params.application_config.web_url());
+ if (IsAppConfigForCastStreaming(params.application_config))
+ web_content_url = GURL(kCastStreamingWebUrl);
+
+ base::Optional<fuchsia::web::CreateContextParams> create_context_params =
+ GetContextParamsForAppConfig(&params.application_config);
+
+ WebContentRunner* component_owner = main_context_.get();
+ if (create_context_params) {
+ component_owner = CreateIsolatedContextForParams(
+ std::move(create_context_params.value()));
}
- // Launch the URL specified in the component |params|.
- GURL app_url = GURL(params.application_config.web_url());
auto cast_component = std::make_unique<CastComponent>(
component_owner, std::move(params), is_headless_);
+
+ // Start the component, which creates and configures the web.Frame, and load
+ // the specified web content into it.
cast_component->SetOnDestroyedCallback(
base::BindOnce(&CastRunner::OnComponentDestroyed, base::Unretained(this),
base::Unretained(cast_component.get())));
cast_component->StartComponent();
- cast_component->LoadUrl(std::move(app_url),
+ cast_component->LoadUrl(std::move(web_content_url),
std::vector<fuchsia::net::http::Header>());
- if (!is_isolated) {
+ if (component_owner == main_context_.get()) {
// If this component has the microphone permission then use it to route
// Audio service requests through.
if (IsPermissionGrantedInAppConfig(
@@ -205,6 +203,7 @@ fuchsia::web::CreateContextParams CastRunner::GetCommonContextParams() {
LOG(WARNING) << "Running in headless mode.";
*params.mutable_features() |= fuchsia::web::ContextFeatureFlags::HEADLESS;
} else {
+ // TODO(crbug.com/1078227): Remove HARDWARE_VIDEO_DECODER_ONLY.
*params.mutable_features() |=
fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER |
fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER_ONLY |
@@ -247,12 +246,13 @@ fuchsia::web::CreateContextParams CastRunner::GetMainContextParams() {
// TODO(crbug.com/1023514): Remove this switch when it is no longer
// necessary.
params.set_unsafely_treat_insecure_origins_as_secure(
- {"allow-running-insecure-content"});
+ {"allow-running-insecure-content", "disable-mixed-content-autoupgrade"});
return params;
}
-fuchsia::web::CreateContextParams CastRunner::GetIsolatedContextParams(
+fuchsia::web::CreateContextParams
+CastRunner::GetIsolatedContextParamsWithFuchsiaDirs(
std::vector<fuchsia::web::ContentDirectoryProvider> content_directories) {
fuchsia::web::CreateContextParams params = GetCommonContextParams();
params.set_content_directories(std::move(content_directories));
@@ -261,6 +261,54 @@ fuchsia::web::CreateContextParams CastRunner::GetIsolatedContextParams(
return params;
}
+fuchsia::web::CreateContextParams
+CastRunner::GetIsolatedContextParamsForCastStreaming() {
+ fuchsia::web::CreateContextParams params = GetCommonContextParams();
+ ApplyCastStreamingContextParams(&params);
+ // TODO(crbug.com/1069746): Use a different FilteredServiceDirectory for Cast
+ // Streaming Contexts.
+ main_services_->ConnectClient(
+ params.mutable_service_directory()->NewRequest());
+ return params;
+}
+
+base::Optional<fuchsia::web::CreateContextParams>
+CastRunner::GetContextParamsForAppConfig(
+ chromium::cast::ApplicationConfig* app_config) {
+ base::Optional<fuchsia::web::CreateContextParams> params;
+
+ if (IsAppConfigForCastStreaming(*app_config)) {
+ // TODO(crbug.com/1082821): Remove this once the CastStreamingReceiver
+ // Component has been implemented.
+ return base::make_optional(GetIsolatedContextParamsForCastStreaming());
+ }
+
+ const bool is_isolated_app =
+ app_config->has_content_directories_for_isolated_application();
+ if (is_isolated_app) {
+ return base::make_optional(
+ GetIsolatedContextParamsWithFuchsiaDirs(std::move(
+ *app_config
+ ->mutable_content_directories_for_isolated_application())));
+ }
+
+ // No need to create an isolated context in other cases.
+ return base::nullopt;
+}
+
+WebContentRunner* CastRunner::CreateIsolatedContextForParams(
+ fuchsia::web::CreateContextParams create_context_params) {
+ // Create an isolated context which will own the CastComponent.
+ auto context =
+ std::make_unique<WebContentRunner>(std::move(create_context_params));
+ context->SetOnEmptyCallback(
+ base::BindOnce(&CastRunner::OnIsolatedContextEmpty,
+ base::Unretained(this), base::Unretained(context.get())));
+ WebContentRunner* raw_context = context.get();
+ isolated_contexts_.insert(std::move(context));
+ return raw_context;
+}
+
void CastRunner::OnIsolatedContextEmpty(WebContentRunner* context) {
auto it = isolated_contexts_.find(context);
DCHECK(it != isolated_contexts_.end());
@@ -279,10 +327,9 @@ void CastRunner::OnAudioServiceRequest(
}
// Otherwise use the Runner's fuchsia.media.Audio service. fuchsia.media.Audio
- // may be used by frames without MICRIPHONE permission to create AudioRenderer
+ // may be used by frames without MICROPHONE permission to create AudioRenderer
// instance.
- base::fuchsia::ComponentContextForCurrentProcess()->svc()->Connect(
- std::move(request));
+ base::ComponentContextForProcess()->svc()->Connect(std::move(request));
}
void CastRunner::OnCameraServiceRequest(
@@ -309,6 +356,5 @@ void CastRunner::OnMetricsRecorderServiceRequest(
reinterpret_cast<CastComponent*>(main_context_->GetAnyComponent());
DCHECK(component);
- component->agent_manager()->ConnectToAgentService(
- component->application_config().agent_url(), std::move(request));
+ component->startup_context()->svc()->Connect(std::move(request));
}
diff --git a/chromium/fuchsia/runners/cast/cast_runner.cmx b/chromium/fuchsia/runners/cast/cast_runner.cmx
index e3d34e48097..495cf2f9841 100644
--- a/chromium/fuchsia/runners/cast/cast_runner.cmx
+++ b/chromium/fuchsia/runners/cast/cast_runner.cmx
@@ -8,6 +8,7 @@
"fuchsia.accessibility.semantics.SemanticsManager",
"fuchsia.camera3.DeviceWatcher",
"fuchsia.device.NameProvider",
+ "fuchsia.feedback.CrashReportingProductRegister",
"fuchsia.fonts.Provider",
"fuchsia.intl.PropertyProvider",
"fuchsia.logger.LogSink",
diff --git a/chromium/fuchsia/runners/cast/cast_runner.h b/chromium/fuchsia/runners/cast/cast_runner.h
index dfd77efa5de..d1b5d5ec043 100644
--- a/chromium/fuchsia/runners/cast/cast_runner.h
+++ b/chromium/fuchsia/runners/cast/cast_runner.h
@@ -70,13 +70,21 @@ class CastRunner : public fuchsia::sys::Runner,
// Handlers used to provide parameters for main & isolated Contexts.
fuchsia::web::CreateContextParams GetCommonContextParams();
fuchsia::web::CreateContextParams GetMainContextParams();
- fuchsia::web::CreateContextParams GetIsolatedContextParams(
+ fuchsia::web::CreateContextParams GetIsolatedContextParamsWithFuchsiaDirs(
std::vector<fuchsia::web::ContentDirectoryProvider> content_directories);
+ // TODO(crbug.com/1082821): Remove this once the CastStreamingReceiver
+ // Component has been implemented.
+ fuchsia::web::CreateContextParams GetIsolatedContextParamsForCastStreaming();
- // Creates a CastRunner configured to serve data from content directories in
- // |component_params|.
+ // Returns CreateContextParams for |app_config|. Returns nullopt if there is
+ // no need to create an isolated context.
+ base::Optional<fuchsia::web::CreateContextParams>
+ GetContextParamsForAppConfig(chromium::cast::ApplicationConfig* app_config);
+
+ // Launches an isolated Context with the given |create_context_params| and
+ // returns the newly created WebContentRunner.
WebContentRunner* CreateIsolatedContextForParams(
- CastComponent::Params* component_params);
+ fuchsia::web::CreateContextParams create_context_params);
// Called when an isolated component terminates, to allow the Context hosting
// it to be torn down.
@@ -99,9 +107,10 @@ class CastRunner : public fuchsia::sys::Runner,
const std::unique_ptr<base::fuchsia::FilteredServiceDirectory> main_services_;
const std::unique_ptr<WebContentRunner> main_context_;
- // Holds fuchsia.web.Contexts used to host isolated components.
const std::unique_ptr<base::fuchsia::FilteredServiceDirectory>
isolated_services_;
+
+ // Holds fuchsia.web.Contexts used to host isolated components.
base::flat_set<std::unique_ptr<WebContentRunner>, base::UniquePtrComparator>
isolated_contexts_;
diff --git a/chromium/fuchsia/runners/cast/cast_runner_integration_test.cc b/chromium/fuchsia/runners/cast/cast_runner_integration_test.cc
index bcbda931614..17962e75d80 100644
--- a/chromium/fuchsia/runners/cast/cast_runner_integration_test.cc
+++ b/chromium/fuchsia/runners/cast/cast_runner_integration_test.cc
@@ -35,7 +35,6 @@
#include "fuchsia/base/frame_test_util.h"
#include "fuchsia/base/fuchsia_dir_scheme.h"
#include "fuchsia/base/mem_buffer_util.h"
-#include "fuchsia/base/release_channel.h"
#include "fuchsia/base/result_receiver.h"
#include "fuchsia/base/string_util.h"
#include "fuchsia/base/test_devtools_list_fetcher.h"
@@ -122,6 +121,13 @@ class FakeApplicationContext : public chromium::cast::ApplicationContext {
return controller_.get();
}
+ base::Optional<int64_t> WaitForApplicationTerminated() {
+ base::RunLoop loop;
+ on_application_terminated_ = loop.QuitClosure();
+ loop.Run();
+ return application_exit_code_;
+ }
+
private:
// chromium::cast::ApplicationContext implementation.
void GetMediaSessionId(GetMediaSessionIdCallback callback) final {
@@ -132,8 +138,16 @@ class FakeApplicationContext : public chromium::cast::ApplicationContext {
final {
controller_ = controller.Bind();
}
+ void OnApplicationExit(int64_t exit_code) final {
+ application_exit_code_ = exit_code;
+ if (on_application_terminated_)
+ std::move(on_application_terminated_).Run();
+ }
chromium::cast::ApplicationControllerPtr controller_;
+
+ base::Optional<int64_t> application_exit_code_;
+ base::OnceClosure on_application_terminated_;
};
class FakeComponentState : public cr_fuchsia::AgentImpl::ComponentStateBase {
@@ -549,8 +563,7 @@ TEST_F(CastRunnerIntegrationTest, IncorrectCastAppId) {
CreateComponentContext(kIncorrectComponentUrl);
StartCastComponent(kIncorrectComponentUrl);
- // Run the loop until the ComponentController is dropped, or a WebComponent is
- // created.
+ // Run the loop until the ComponentController is dropped.
base::RunLoop run_loop;
component_controller_.set_error_handler([&run_loop](zx_status_t status) {
EXPECT_EQ(status, ZX_ERR_PEER_CLOSED);
@@ -865,26 +878,106 @@ TEST_F(CastRunnerIntegrationTest, LegacyMetricsRedirect) {
CreateComponentContext(component_url);
EXPECT_NE(component_context_, nullptr);
+ base::RunLoop run_loop;
+
+ // Add MetricsRecorder the the component's incoming_services.
+ component_services_.AddPublicService(
+ std::make_unique<vfs::Service>(
+ [&run_loop](zx::channel request, async_dispatcher_t* dispatcher) {
+ run_loop.Quit();
+ }),
+ fuchsia::legacymetrics::MetricsRecorder::Name_);
+
StartCastComponent(component_url);
- // Wait until we see the CastRunner connect to the LegacyMetrics service.
- base::RunLoop run_loop;
- component_state_created_callback_ = base::BindOnce(
- [](FakeComponentState** component_state,
- base::RepeatingClosure quit_closure) {
- (*component_state)
- ->outgoing_directory()
- ->AddPublicService(
- std::make_unique<vfs::Service>(
- [quit_closure](zx::channel, async_dispatcher_t*) {
- quit_closure.Run();
- }),
- fuchsia::legacymetrics::MetricsRecorder::Name_);
- },
- base::Unretained(&component_state_), run_loop.QuitClosure());
+ // Wait until we see the CastRunner connect to the MetricsRecorder service.
run_loop.Run();
}
+// Verifies that the ApplicationContext::OnApplicationTerminated() is notified
+// with the component exit code if the web content closes itself.
+TEST_F(CastRunnerIntegrationTest, OnApplicationTerminated_WindowClose) {
+ const GURL url = test_server_.GetURL(kBlankAppUrl);
+ app_config_manager_.AddApp(kTestAppId, url);
+
+ CreateComponentContextAndStartComponent();
+
+ // It is possible to observe the ComponentController close before
+ // OnApplicationTerminated() is received, so ignore that.
+ component_controller_.set_error_handler([](zx_status_t) {});
+
+ // Have the web content close itself, and wait for OnApplicationTerminated().
+ EXPECT_EQ(ExecuteJavaScript("window.close()"), "undefined");
+ base::Optional<zx_status_t> exit_code =
+ component_state_->application_context()->WaitForApplicationTerminated();
+ ASSERT_TRUE(exit_code);
+ EXPECT_EQ(exit_code.value(), ZX_OK);
+}
+
+// Verifies that the ComponentController reports TerminationReason::EXITED and
+// exit code ZX_OK if the web content terminates itself.
+// TODO(https://crbug.com/1066833): Make this a WebRunner test.
+TEST_F(CastRunnerIntegrationTest, OnTerminated_WindowClose) {
+ const GURL url = test_server_.GetURL(kBlankAppUrl);
+ app_config_manager_.AddApp(kTestAppId, url);
+
+ CreateComponentContextAndStartComponent();
+
+ // Register an handler on the ComponentController channel, for the
+ // OnTerminated event.
+ base::RunLoop exit_code_loop;
+ component_controller_.set_error_handler(
+ [quit_loop = exit_code_loop.QuitClosure()](zx_status_t) {
+ quit_loop.Run();
+ ADD_FAILURE();
+ });
+ component_controller_.events().OnTerminated =
+ [quit_loop = exit_code_loop.QuitClosure()](
+ int64_t exit_code, fuchsia::sys::TerminationReason reason) {
+ quit_loop.Run();
+ EXPECT_EQ(reason, fuchsia::sys::TerminationReason::EXITED);
+ EXPECT_EQ(exit_code, ZX_OK);
+ };
+
+ // Have the web content close itself, and wait for OnTerminated().
+ EXPECT_EQ(ExecuteJavaScript("window.close()"), "undefined");
+ exit_code_loop.Run();
+
+ component_controller_.Unbind();
+}
+
+// Verifies that the ComponentController reports TerminationReason::EXITED and
+// exit code ZX_OK if Kill() is used.
+// TODO(https://crbug.com/1066833): Make this a WebRunner test.
+TEST_F(CastRunnerIntegrationTest, OnTerminated_ComponentKill) {
+ const GURL url = test_server_.GetURL(kBlankAppUrl);
+ app_config_manager_.AddApp(kTestAppId, url);
+
+ CreateComponentContextAndStartComponent();
+
+ // Register an handler on the ComponentController channel, for the
+ // OnTerminated event.
+ base::RunLoop exit_code_loop;
+ component_controller_.set_error_handler(
+ [quit_loop = exit_code_loop.QuitClosure()](zx_status_t) {
+ quit_loop.Run();
+ ADD_FAILURE();
+ });
+ component_controller_.events().OnTerminated =
+ [quit_loop = exit_code_loop.QuitClosure()](
+ int64_t exit_code, fuchsia::sys::TerminationReason reason) {
+ quit_loop.Run();
+ EXPECT_EQ(reason, fuchsia::sys::TerminationReason::EXITED);
+ EXPECT_EQ(exit_code, ZX_OK);
+ };
+
+ // Kill() the component and wait for OnTerminated().
+ component_controller_->Kill();
+ exit_code_loop.Run();
+
+ component_controller_.Unbind();
+}
+
TEST_F(CastRunnerIntegrationTest, WebGLContextAbsentWithoutVulkanFeature) {
const char kTestPath[] = "/webgl_presence.html";
const GURL test_url = test_server_.GetURL(kTestPath);
diff --git a/chromium/fuchsia/runners/cast/cast_streaming.cc b/chromium/fuchsia/runners/cast/cast_streaming.cc
new file mode 100644
index 00000000000..88754ededc6
--- /dev/null
+++ b/chromium/fuchsia/runners/cast/cast_streaming.cc
@@ -0,0 +1,66 @@
+// Copyright 2020 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/runners/cast/cast_streaming.h"
+
+#include "base/fuchsia/file_utils.h"
+#include "base/path_service.h"
+
+namespace {
+
+constexpr char kCastStreamingAppUrl[] = "cast-streaming:receiver";
+constexpr char kCastDataDirectory[] = "fuchsia/runners/cast/data";
+constexpr char kCastStreamingContentDirectoryName[] = "cast-streaming";
+
+// Returns the content directories for the Cast Streaming application.
+std::vector<fuchsia::web::ContentDirectoryProvider>
+GetCastStreamingContentDirectories() {
+ base::FilePath pkg_path;
+ bool success = base::PathService::Get(base::DIR_ASSETS, &pkg_path);
+ DCHECK(success);
+
+ fuchsia::web::ContentDirectoryProvider content_directory;
+ content_directory.set_directory(
+ base::fuchsia::OpenDirectory(pkg_path.AppendASCII(kCastDataDirectory)));
+ content_directory.set_name(kCastStreamingContentDirectoryName);
+ std::vector<fuchsia::web::ContentDirectoryProvider> content_directories;
+ content_directories.emplace_back(std::move(content_directory));
+
+ return content_directories;
+}
+
+} // namespace
+
+const char kCastStreamingWebUrl[] =
+ "fuchsia-dir://cast-streaming/receiver.html";
+
+const char kCastStreamingMessagePortOrigin[] = "cast-streaming:receiver";
+
+const char kCastStreamingMessagePortName[] = "cast.__platform__.cast_transport";
+
+bool IsAppConfigForCastStreaming(
+ const chromium::cast::ApplicationConfig& application_config) {
+ return application_config.web_url() == kCastStreamingAppUrl;
+}
+
+void ApplyCastStreamingContextParams(
+ fuchsia::web::CreateContextParams* params) {
+ // Disable the HARDWARE_VIDEO_DECODER_ONLY tag.
+ // TODO(crbug.com/1078227): Remove HARDWARE_VIDEO_DECODER_ONLY once it is
+ // no longer set in CastRunner::CommonContextParams(). For now, this is
+ // required to enable software decoders.
+ *params->mutable_features() &=
+ ~fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER_ONLY;
+
+ // Disable the WIDEVINE_CDM tag.
+ // TODO(crbug.com/1069746): Remove this once WIDEVINE_CDM is no longer set in
+ // CastRunner::CommonContextParams().
+ *params->mutable_features() &=
+ ~fuchsia::web::ContextFeatureFlags::WIDEVINE_CDM;
+
+ *params->mutable_features() |= fuchsia::web::ContextFeatureFlags::NETWORK;
+
+ // Set the content directory with the streaming app.
+ params->set_content_directories(GetCastStreamingContentDirectories());
+}
diff --git a/chromium/fuchsia/runners/cast/cast_streaming.h b/chromium/fuchsia/runners/cast/cast_streaming.h
new file mode 100644
index 00000000000..0bc7f650ea4
--- /dev/null
+++ b/chromium/fuchsia/runners/cast/cast_streaming.h
@@ -0,0 +1,33 @@
+// Copyright 2020 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 FUCHSIA_RUNNERS_CAST_CAST_STREAMING_H_
+#define FUCHSIA_RUNNERS_CAST_CAST_STREAMING_H_
+
+#include <fuchsia/web/cpp/fidl.h>
+
+#include "base/callback.h"
+#include "base/strings/string_piece.h"
+#include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
+
+// TODO(crbug.com/1082821): Remove unused methods here once the
+// Cast Streaming Receiver component has been implemented.
+
+// URL for the Cast Streaming application.
+extern const char kCastStreamingWebUrl[];
+
+// Origin value for the Cast Streaming MessagePort.
+extern const char kCastStreamingMessagePortOrigin[];
+
+// Name of the Cast Streaming MessagePort.
+extern const char kCastStreamingMessagePortName[];
+
+// Returns true if |application_config| is a cast streaming application.
+bool IsAppConfigForCastStreaming(
+ const chromium::cast::ApplicationConfig& application_config);
+
+// Modifies |params| to apply Cast Streaming-specific Context Params.
+void ApplyCastStreamingContextParams(fuchsia::web::CreateContextParams* params);
+
+#endif // FUCHSIA_RUNNERS_CAST_CAST_STREAMING_H_
diff --git a/chromium/fuchsia/runners/cast/data/receiver.html b/chromium/fuchsia/runners/cast/data/receiver.html
new file mode 100644
index 00000000000..29a914e1ae3
--- /dev/null
+++ b/chromium/fuchsia/runners/cast/data/receiver.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!--
+Copyright 2020 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.
+-->
+<html>
+<head>
+ <meta charset="utf-8">
+ <style>
+ video {
+ background-color: black;
+ max-width: 100%;
+ height: auto;
+ }
+ </style>
+</head>
+
+<body>
+ <video src="data:cast_streaming_receiver" autoplay>
+
+ <script>
+ // The Cast Streaming session must stop when the stream is no longer visible. crbug.com/1111886
+ document.addEventListener('visibilitychange', function(e) {
+ if (document.hidden) {
+ window.close();
+ }
+ });
+
+ // TODO(crbug.com/1087528): This should not be necessary. Figure out why
+ // autoplay is not enough here.
+ var video = document.querySelector('video');
+ video.play();
+ </script>
+</body>
+</html>
diff --git a/chromium/fuchsia/runners/cast/main.cc b/chromium/fuchsia/runners/cast/main.cc
index e6e0f47d04a..8ec770080bc 100644
--- a/chromium/fuchsia/runners/cast/main.cc
+++ b/chromium/fuchsia/runners/cast/main.cc
@@ -5,7 +5,7 @@
#include <lib/sys/cpp/component_context.h>
#include "base/command_line.h"
-#include "base/fuchsia/default_context.h"
+#include "base/fuchsia/process_context.h"
#include "base/fuchsia/scoped_service_binding.h"
#include "base/message_loop/message_pump_type.h"
#include "base/optional.h"
@@ -13,12 +13,19 @@
#include "base/task/single_thread_task_executor.h"
#include "base/values.h"
#include "fuchsia/base/config_reader.h"
+#include "fuchsia/base/feedback_registration.h"
#include "fuchsia/base/fuchsia_dir_scheme.h"
#include "fuchsia/base/init_logging.h"
+#include "fuchsia/base/inspect.h"
#include "fuchsia/runners/cast/cast_runner.h"
namespace {
+constexpr char kCrashProductName[] = "FuchsiaCastRunner";
+// TODO(https://fxbug.dev/51490): Use a programmatic mechanism to obtain this.
+constexpr char kComponentUrl[] =
+ "fuchsia-pkg://fuchsia.com/cast_runner#meta/cast_runner.cmx";
+
bool IsHeadless() {
constexpr char kHeadlessConfigKey[] = "headless";
@@ -37,6 +44,8 @@ int main(int argc, char** argv) {
base::SingleThreadTaskExecutor io_task_executor(base::MessagePumpType::IO);
base::RunLoop run_loop;
+ cr_fuchsia::RegisterCrashReportingFields(kComponentUrl, kCrashProductName);
+
base::CommandLine::Init(argc, argv);
CHECK(cr_fuchsia::InitLoggingFromCommandLine(
*base::CommandLine::ForCurrentProcess()))
@@ -46,12 +55,12 @@ int main(int argc, char** argv) {
CastRunner runner(IsHeadless());
base::fuchsia::ScopedServiceBinding<fuchsia::sys::Runner> binding(
- base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get(),
- &runner);
+ base::ComponentContextForProcess()->outgoing().get(), &runner);
+
+ base::ComponentContextForProcess()->outgoing()->ServeFromStartupInfo();
- base::fuchsia::ComponentContextForCurrentProcess()
- ->outgoing()
- ->ServeFromStartupInfo();
+ // Publish version information for this component to Inspect.
+ cr_fuchsia::PublishVersionInfoToInspect(base::ComponentInspectorForProcess());
// Run until there are no Components, or the last service client channel is
// closed.
diff --git a/chromium/fuchsia/runners/cast/named_message_port_connector.cc b/chromium/fuchsia/runners/cast/named_message_port_connector.cc
index 515403889b9..76b80b347c2 100644
--- a/chromium/fuchsia/runners/cast/named_message_port_connector.cc
+++ b/chromium/fuchsia/runners/cast/named_message_port_connector.cc
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/path_service.h"
#include "base/strings/string_piece.h"
diff --git a/chromium/fuchsia/runners/cast/pending_cast_component.cc b/chromium/fuchsia/runners/cast/pending_cast_component.cc
index 16dce5b11b2..b6c353763a8 100644
--- a/chromium/fuchsia/runners/cast/pending_cast_component.cc
+++ b/chromium/fuchsia/runners/cast/pending_cast_component.cc
@@ -163,5 +163,7 @@ void PendingCastComponent::MaybeLaunchComponent() {
// user-after-free of |this|.
params_.url_rewrite_rules_provider.set_error_handler(nullptr);
+ params_.application_context = application_context_.Unbind();
+
delegate_->LaunchPendingComponent(this, std::move(params_));
}
diff --git a/chromium/fuchsia/runners/common/web_component.cc b/chromium/fuchsia/runners/common/web_component.cc
index 53ef3d1e641..edaf54562da 100644
--- a/chromium/fuchsia/runners/common/web_component.cc
+++ b/chromium/fuchsia/runners/common/web_component.cc
@@ -9,10 +9,10 @@
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fit/function.h>
#include <lib/sys/cpp/component_context.h>
+#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <utility>
#include "base/bind.h"
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/logging.h"
#include "fuchsia/runners/common/web_content_runner.h"
@@ -25,9 +25,9 @@ WebComponent::WebComponent(
: runner_(runner),
startup_context_(std::move(context)),
controller_binding_(this),
- module_context_(startup_context()
- ->svc()
- ->Connect<fuchsia::modular::ModuleContext>()) {
+ module_context_(
+ startup_context()->svc()->Connect<fuchsia::modular::ModuleContext>()),
+ navigation_listener_binding_(this) {
DCHECK(runner);
// If the ComponentController request is valid then bind it, and configure it
@@ -67,13 +67,19 @@ void WebComponent::StartComponent() {
create_params.set_enable_remote_debugging(enable_remote_debugging_);
frame_ = runner_->CreateFrame(std::move(create_params));
- // If the Frame unexpectedly disconnect us then tear-down this Component.
+ // If the Frame unexpectedly disconnects then tear-down this Component.
+ // ZX_OK indicates intentional termination (e.g. via window.close()).
+ // ZX_ERR_PEER_CLOSED will usually indicate a crash, reported elsewhere.
+ // Therefore only log other, more unusual, |status| codes.
frame_.set_error_handler([this](zx_status_t status) {
- ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status)
- << " Frame disconnected";
- DestroyComponent(0, fuchsia::sys::TerminationReason::EXITED);
+ if (status != ZX_OK && status != ZX_ERR_PEER_CLOSED)
+ ZX_LOG(ERROR, status) << " Frame disconnected";
+ DestroyComponent(status, fuchsia::sys::TerminationReason::EXITED);
});
+ // Observe the Frame for failures, via navigation state change events.
+ frame_->SetNavigationEventListener(navigation_listener_binding_.NewBinding());
+
if (startup_context()->has_outgoing_directory_request()) {
// Publish outgoing services and start serving component's outgoing
// directory.
@@ -110,8 +116,8 @@ void WebComponent::LoadUrl(
}
void WebComponent::Kill() {
- // Signal abnormal process termination.
- DestroyComponent(1, fuchsia::sys::TerminationReason::RUNNER_TERMINATED);
+ // Signal normal termination, since the caller requested it.
+ DestroyComponent(ZX_OK, fuchsia::sys::TerminationReason::EXITED);
}
void WebComponent::Detach() {
@@ -122,19 +128,53 @@ void WebComponent::CreateView(
zx::eventpair view_token_value,
fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services,
fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services) {
+ scenic::ViewRefPair view_ref_pair = scenic::ViewRefPair::New();
+ CreateViewWithViewRef(std::move(view_token_value),
+ std::move(view_ref_pair.control_ref),
+ std::move(view_ref_pair.view_ref));
+}
+
+void WebComponent::CreateViewWithViewRef(
+ zx::eventpair view_token_value,
+ fuchsia::ui::views::ViewRefControl control_ref,
+ fuchsia::ui::views::ViewRef view_ref) {
DCHECK(frame_);
- DCHECK(!view_is_bound_);
+ if (view_is_bound_) {
+ LOG(ERROR) << "CreateView() called more than once.";
+ DestroyComponent(ZX_ERR_BAD_STATE, fuchsia::sys::TerminationReason::EXITED);
+ return;
+ }
fuchsia::ui::views::ViewToken view_token;
view_token.value = std::move(view_token_value);
- frame_->CreateView(std::move(view_token));
+ frame_->CreateViewWithViewRef(std::move(view_token), std::move(control_ref),
+ std::move(view_ref));
view_is_bound_ = true;
}
-void WebComponent::DestroyComponent(int termination_exit_code,
+void WebComponent::OnNavigationStateChanged(
+ fuchsia::web::NavigationState change,
+ OnNavigationStateChangedCallback callback) {
+ if (change.has_page_type()) {
+ switch (change.page_type()) {
+ case fuchsia::web::PageType::ERROR:
+ DestroyComponent(ZX_ERR_INTERNAL,
+ fuchsia::sys::TerminationReason::EXITED);
+ break;
+ case fuchsia::web::PageType::NORMAL:
+ break;
+ }
+ }
+ // Do not touch |this|, which may have been deleted by DestroyComponent().
+
+ // |callback| is safe to run, since it is on the stack.
+ callback();
+}
+
+void WebComponent::DestroyComponent(int64_t exit_code,
fuchsia::sys::TerminationReason reason) {
termination_reason_ = reason;
- termination_exit_code_ = termination_exit_code;
+ termination_exit_code_ = exit_code;
runner_->DestroyComponent(this);
}
diff --git a/chromium/fuchsia/runners/common/web_component.h b/chromium/fuchsia/runners/common/web_component.h
index 4653f465058..0ed8cebbc42 100644
--- a/chromium/fuchsia/runners/common/web_component.h
+++ b/chromium/fuchsia/runners/common/web_component.h
@@ -18,7 +18,6 @@
#include "base/fuchsia/scoped_service_binding.h"
#include "base/fuchsia/startup_context.h"
-#include "base/logging.h"
#include "fuchsia/base/lifecycle_impl.h"
#include "url/gurl.h"
@@ -30,7 +29,8 @@ class WebContentRunner;
// (e.g. Cast applications) can extend this class to configure the Frame to
// their needs, publish additional APIs, etc.
class WebComponent : public fuchsia::sys::ComponentController,
- public fuchsia::ui::app::ViewProvider {
+ public fuchsia::ui::app::ViewProvider,
+ public fuchsia::web::NavigationEventListener {
public:
// Creates a WebComponent encapsulating a web.Frame. A ViewProvider service
// will be published to the service-directory specified by |startup_context|,
@@ -60,6 +60,12 @@ class WebComponent : public fuchsia::sys::ComponentController,
WebContentRunner* runner() const { return runner_; }
+ // Returns the component's startup context (e.g. incoming services, public
+ // service directory, etc).
+ base::fuchsia::StartupContext* startup_context() const {
+ return startup_context_.get();
+ }
+
protected:
// fuchsia::sys::ComponentController implementation.
void Kill() override;
@@ -71,18 +77,24 @@ class WebComponent : public fuchsia::sys::ComponentController,
fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services,
fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services)
override;
+ void CreateViewWithViewRef(zx::eventpair view_token,
+ fuchsia::ui::views::ViewRefControl control_ref,
+ fuchsia::ui::views::ViewRef view_ref) override;
+
+ // fuchsia::web::NavigationEventListener implementation.
+ // Used to detect when the Frame enters an error state (e.g. the top-level
+ // content's Renderer process crashes).
+ void OnNavigationStateChanged(
+ fuchsia::web::NavigationState change,
+ OnNavigationStateChangedCallback callback) override;
// Reports the supplied exit-code and reason to the |controller_binding_| and
- // requests that the |runner_| delete this component.
- virtual void DestroyComponent(int termination_exit_code,
+ // requests that the |runner_| delete this component. The EXITED |reason| is
+ // used to indicate Frame disconnection, in which case the |exit_code| is set
+ // to the status reported by the FramePtr's error handler.
+ virtual void DestroyComponent(int64_t exit_code,
fuchsia::sys::TerminationReason reason);
- // Returns the component's startup context (e.g. incoming services, public
- // service directory, etc).
- base::fuchsia::StartupContext* startup_context() const {
- return startup_context_.get();
- }
-
private:
WebContentRunner* const runner_ = nullptr;
const std::unique_ptr<base::fuchsia::StartupContext> startup_context_;
@@ -105,13 +117,18 @@ class WebComponent : public fuchsia::sys::ComponentController,
// sys::ComponentController::OnTerminated event.
fuchsia::sys::TerminationReason termination_reason_ =
fuchsia::sys::TerminationReason::UNKNOWN;
- int termination_exit_code_ = 0;
+ int64_t termination_exit_code_ = 0;
bool view_is_bound_ = false;
bool component_started_ = false;
bool enable_remote_debugging_ = false;
+ // Used to watch for failures of the Frame's web content, including Renderer
+ // process crashes.
+ fidl::Binding<fuchsia::web::NavigationEventListener>
+ navigation_listener_binding_;
+
DISALLOW_COPY_AND_ASSIGN(WebComponent);
};
diff --git a/chromium/fuchsia/runners/common/web_content_runner.cc b/chromium/fuchsia/runners/common/web_content_runner.cc
index 22ea1651c35..34140e73d25 100644
--- a/chromium/fuchsia/runners/common/web_content_runner.cc
+++ b/chromium/fuchsia/runners/common/web_content_runner.cc
@@ -12,9 +12,9 @@
#include "base/bind.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/file_utils.h"
#include "base/fuchsia/fuchsia_logging.h"
+#include "base/fuchsia/process_context.h"
#include "base/fuchsia/scoped_service_binding.h"
#include "base/fuchsia/startup_context.h"
#include "base/logging.h"
@@ -26,7 +26,7 @@ namespace {
fuchsia::web::ContextPtr CreateWebContext(
fuchsia::web::CreateContextParams context_params) {
- auto context_provider = base::fuchsia::ComponentContextForCurrentProcess()
+ auto context_provider = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::web::ContextProvider>();
fuchsia::web::ContextPtr web_context;
diff --git a/chromium/fuchsia/runners/web/OWNERS b/chromium/fuchsia/runners/web/OWNERS
new file mode 100644
index 00000000000..2f43650c9db
--- /dev/null
+++ b/chromium/fuchsia/runners/web/OWNERS
@@ -0,0 +1,2 @@
+per-file *.cmx=set noparent
+per-file *.cmx=file://fuchsia/SECURITY_OWNERS
diff --git a/chromium/fuchsia/runners/web/main.cc b/chromium/fuchsia/runners/web/main.cc
index 719419d8350..267fe44de47 100644
--- a/chromium/fuchsia/runners/web/main.cc
+++ b/chromium/fuchsia/runners/web/main.cc
@@ -5,14 +5,15 @@
#include <lib/sys/cpp/component_context.h>
#include "base/command_line.h"
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/file_utils.h"
+#include "base/fuchsia/process_context.h"
#include "base/fuchsia/scoped_service_binding.h"
#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_executor.h"
#include "fuchsia/base/fuchsia_dir_scheme.h"
#include "fuchsia/base/init_logging.h"
+#include "fuchsia/base/inspect.h"
#include "fuchsia/runners/buildflags.h"
#include "fuchsia/runners/common/web_content_runner.h"
@@ -60,12 +61,12 @@ int main(int argc, char** argv) {
WebContentRunner runner(std::move(get_context_params_callback));
base::fuchsia::ScopedServiceBinding<fuchsia::sys::Runner> binding(
- base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get(),
- &runner);
+ base::ComponentContextForProcess()->outgoing().get(), &runner);
- base::fuchsia::ComponentContextForCurrentProcess()
- ->outgoing()
- ->ServeFromStartupInfo();
+ base::ComponentContextForProcess()->outgoing()->ServeFromStartupInfo();
+
+ // Publish version information for this component to Inspect.
+ cr_fuchsia::PublishVersionInfoToInspect(base::ComponentInspectorForProcess());
// Run until there are no Components, or the last service client channel is
// closed.
diff --git a/chromium/fuchsia/runners/web/web_runner_smoke_test.cc b/chromium/fuchsia/runners/web/web_runner_smoke_test.cc
index 91ba0d00ddb..bd38e2ca004 100644
--- a/chromium/fuchsia/runners/web/web_runner_smoke_test.cc
+++ b/chromium/fuchsia/runners/web/web_runner_smoke_test.cc
@@ -8,7 +8,7 @@
#include <lib/sys/cpp/component_context.h>
#include "base/bind.h"
-#include "base/fuchsia/default_context.h"
+#include "base/fuchsia/process_context.h"
#include "base/fuchsia/scoped_service_binding.h"
#include "base/fuchsia/service_provider_impl.h"
#include "base/test/task_environment.h"
@@ -107,7 +107,7 @@ TEST_F(WebRunnerSmokeTest, MAYBE_RequestHtmlAndImage) {
fuchsia::sys::LaunchInfo launch_info = LaunchInfoWithServices();
launch_info.url = test_server_.GetURL("/test.html").spec();
- auto launcher = base::fuchsia::ComponentContextForCurrentProcess()
+ auto launcher = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::sys::Launcher>();
@@ -128,7 +128,7 @@ TEST_F(WebRunnerSmokeTest, LifecycleTerminate) {
launch_info.url = test_server_.GetURL("/test.html").spec();
launch_info.directory_request = directory.NewRequest().TakeChannel();
- auto launcher = base::fuchsia::ComponentContextForCurrentProcess()
+ auto launcher = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::sys::Launcher>();
@@ -157,7 +157,7 @@ TEST_F(WebRunnerSmokeTest, ComponentExitOnFrameClose) {
fuchsia::sys::LaunchInfo launch_info = LaunchInfoWithServices();
launch_info.url = test_server_.GetURL("/window_close.html").spec();
- auto launcher = base::fuchsia::ComponentContextForCurrentProcess()
+ auto launcher = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::sys::Launcher>();
@@ -204,7 +204,7 @@ TEST_F(WebRunnerSmokeTest, RemoveSelfFromStoryOnFrameClose) {
launch_info.additional_services->names.emplace_back(
fuchsia::modular::ModuleContext::Name_);
- auto launcher = base::fuchsia::ComponentContextForCurrentProcess()
+ auto launcher = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::sys::Launcher>();