summaryrefslogtreecommitdiff
path: root/chromium/fuchsia
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
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')
-rw-r--r--chromium/fuchsia/BUILD.gn2
-rw-r--r--chromium/fuchsia/base/BUILD.gn23
-rw-r--r--chromium/fuchsia/base/DEPS1
-rw-r--r--chromium/fuchsia/base/agent_impl.cc1
-rw-r--r--chromium/fuchsia/base/agent_impl.h1
-rw-r--r--chromium/fuchsia/base/agent_manager.h1
-rw-r--r--chromium/fuchsia/base/config_reader.cc16
-rw-r--r--chromium/fuchsia/base/context_provider_test_connector.cc12
-rw-r--r--chromium/fuchsia/base/context_provider_test_connector.h1
-rw-r--r--chromium/fuchsia/base/feedback_registration.cc30
-rw-r--r--chromium/fuchsia/base/feedback_registration.h22
-rw-r--r--chromium/fuchsia/base/frame_test_util.cc15
-rw-r--r--chromium/fuchsia/base/frame_test_util.h6
-rw-r--r--chromium/fuchsia/base/inspect.cc28
-rw-r--r--chromium/fuchsia/base/inspect.h20
-rw-r--r--chromium/fuchsia/base/inspect_unittest.cc95
-rw-r--r--chromium/fuchsia/base/legacymetrics_client.cc85
-rw-r--r--chromium/fuchsia/base/legacymetrics_client.h17
-rw-r--r--chromium/fuchsia/base/legacymetrics_client_unittest.cc111
-rw-r--r--chromium/fuchsia/base/legacymetrics_histogram_flattener.cc1
-rw-r--r--chromium/fuchsia/cast_streaming/BUILD.gn9
-rw-r--r--chromium/fuchsia/cast_streaming/DEPS2
-rw-r--r--chromium/fuchsia/cast_streaming/cast_streaming.cc24
-rw-r--r--chromium/fuchsia/cast_streaming/cast_streaming_session.cc123
-rw-r--r--chromium/fuchsia/cast_streaming/public/cast_streaming.h25
-rw-r--r--chromium/fuchsia/cast_streaming/public/cast_streaming_session.h53
-rw-r--r--chromium/fuchsia/cast_streaming/stream_consumer.cc148
-rw-r--r--chromium/fuchsia/cast_streaming/stream_consumer.h46
-rw-r--r--chromium/fuchsia/cipd/BUILD.gn12
-rw-r--r--chromium/fuchsia/engine/BUILD.gn18
-rw-r--r--chromium/fuchsia/engine/DEPS1
-rw-r--r--chromium/fuchsia/engine/OWNERS2
-rw-r--r--chromium/fuchsia/engine/browser/DEPS2
-rw-r--r--chromium/fuchsia/engine/browser/accessibility_bridge_browsertest.cc2
-rw-r--r--chromium/fuchsia/engine/browser/cast_streaming_browsertest.cc129
-rw-r--r--chromium/fuchsia/engine/browser/cast_streaming_session_client.cc111
-rw-r--r--chromium/fuchsia/engine/browser/cast_streaming_session_client.h57
-rw-r--r--chromium/fuchsia/engine/browser/context_impl.cc12
-rw-r--r--chromium/fuchsia/engine/browser/context_impl.h9
-rw-r--r--chromium/fuchsia/engine/browser/cookie_manager_impl.cc15
-rw-r--r--chromium/fuchsia/engine/browser/cookie_manager_impl_unittest.cc3
-rw-r--r--chromium/fuchsia/engine/browser/event_filter.cc1
-rw-r--r--chromium/fuchsia/engine/browser/frame_impl.cc126
-rw-r--r--chromium/fuchsia/engine/browser/frame_impl.h26
-rw-r--r--chromium/fuchsia/engine/browser/frame_impl_browsertest.cc89
-rw-r--r--chromium/fuchsia/engine/browser/frame_window_tree_host.cc3
-rw-r--r--chromium/fuchsia/engine/browser/frame_window_tree_host.h1
-rw-r--r--chromium/fuchsia/engine/browser/media_resource_provider_service.cc12
-rw-r--r--chromium/fuchsia/engine/browser/navigation_controller_impl.cc99
-rw-r--r--chromium/fuchsia/engine/browser/navigation_controller_impl.h6
-rw-r--r--chromium/fuchsia/engine/browser/web_engine_browser_context.cc5
-rw-r--r--chromium/fuchsia/engine/browser/web_engine_content_browser_client.cc9
-rw-r--r--chromium/fuchsia/engine/browser/web_engine_net_log_observer.cc3
-rw-r--r--chromium/fuchsia/engine/cast_streaming_session.mojom59
-rw-r--r--chromium/fuchsia/engine/common/cast_streaming.cc24
-rw-r--r--chromium/fuchsia/engine/common/cast_streaming.h16
-rw-r--r--chromium/fuchsia/engine/common/web_engine_content_client.cc1
-rw-r--r--chromium/fuchsia/engine/context_provider.cmx1
-rw-r--r--chromium/fuchsia/engine/context_provider_impl.cc80
-rw-r--r--chromium/fuchsia/engine/context_provider_impl_unittest.cc32
-rw-r--r--chromium/fuchsia/engine/context_provider_main.cc23
-rw-r--r--chromium/fuchsia/engine/on_load_script_injector.mojom1
-rw-r--r--chromium/fuchsia/engine/renderer/cast_streaming_demuxer.cc352
-rw-r--r--chromium/fuchsia/engine/renderer/cast_streaming_demuxer.h84
-rw-r--r--chromium/fuchsia/engine/renderer/cast_streaming_receiver.cc128
-rw-r--r--chromium/fuchsia/engine/renderer/cast_streaming_receiver.h63
-rw-r--r--chromium/fuchsia/engine/renderer/on_load_script_injector.cc5
-rw-r--r--chromium/fuchsia/engine/renderer/on_load_script_injector.h3
-rw-r--r--chromium/fuchsia/engine/renderer/url_request_rules_receiver.cc16
-rw-r--r--chromium/fuchsia/engine/renderer/url_request_rules_receiver.h22
-rw-r--r--chromium/fuchsia/engine/renderer/web_engine_content_renderer_client.cc47
-rw-r--r--chromium/fuchsia/engine/renderer/web_engine_content_renderer_client.h21
-rw-r--r--chromium/fuchsia/engine/renderer/web_engine_render_frame_observer.cc25
-rw-r--r--chromium/fuchsia/engine/renderer/web_engine_render_frame_observer.h50
-rw-r--r--chromium/fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.cc5
-rw-r--r--chromium/fuchsia/engine/web_engine_debug_integration_test.cc4
-rw-r--r--chromium/fuchsia/engine/web_engine_integration_test.cc135
-rw-r--r--chromium/fuchsia/engine/web_engine_integration_tests.cmx1
-rw-r--r--chromium/fuchsia/fidl/cast/application_context.fidl7
-rw-r--r--chromium/fuchsia/http/http_service_main.cc6
-rw-r--r--chromium/fuchsia/mojom/BUILD.gn20
-rw-r--r--chromium/fuchsia/mojom/OWNERS2
-rw-r--r--chromium/fuchsia/mojom/example.typemap16
-rw-r--r--chromium/fuchsia/mojom/test_typemaps.gni5
-rw-r--r--chromium/fuchsia/release_channel.gni15
-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
110 files changed, 2976 insertions, 707 deletions
diff --git a/chromium/fuchsia/BUILD.gn b/chromium/fuchsia/BUILD.gn
index fe99326c784..f849593928b 100644
--- a/chromium/fuchsia/BUILD.gn
+++ b/chromium/fuchsia/BUILD.gn
@@ -4,8 +4,6 @@
assert(is_fuchsia)
-import("//build/buildflag_header.gni")
-import("//fuchsia/release_channel.gni")
import("//third_party/fuchsia-sdk/sdk/build/fidl_library.gni")
fidl_library("cast_fidl") {
diff --git a/chromium/fuchsia/base/BUILD.gn b/chromium/fuchsia/base/BUILD.gn
index 2dba9680aad..4e0d73dd164 100644
--- a/chromium/fuchsia/base/BUILD.gn
+++ b/chromium/fuchsia/base/BUILD.gn
@@ -4,30 +4,37 @@
assert(is_fuchsia)
-import("//build/buildflag_header.gni")
import("//build/config/fuchsia/generate_runner_scripts.gni")
-import("//fuchsia/release_channel.gni")
import("//testing/test.gni")
# Integration helpers for commonly used fuchsia.* APIs.
source_set("base") {
sources = [
"config_reader.cc",
+ "feedback_registration.cc",
"fuchsia_dir_scheme.cc",
"init_logging.cc",
+ "inspect.cc",
"mem_buffer_util.cc",
"string_util.cc",
]
public = [
"config_reader.h",
+ "feedback_registration.h",
"fuchsia_dir_scheme.h",
"init_logging.h",
+ "inspect.h",
"mem_buffer_util.h",
"string_util.h",
]
deps = [
"//base",
+ "//components/version_info",
+ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.feedback",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mem",
+ "//third_party/fuchsia-sdk/sdk/pkg/fdio",
+ "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
+ "//third_party/fuchsia-sdk/sdk/pkg/sys_inspect_cpp",
"//url",
]
}
@@ -78,13 +85,6 @@ source_set("legacymetrics") {
friend = [ ":*" ]
}
-# Used to propagate release-qualified package names to integration test code.
-buildflag_header("release_channel_buildflags") {
- header = "release_channel.h"
- flags = [ "FUCHSIA_RELEASE_CHANNEL_SUFFIX=\"$release_channel_suffix\"" ]
- visibility = [ "//fuchsia/*" ]
-}
-
source_set("test_support") {
testonly = true
sources = [
@@ -106,7 +106,6 @@ source_set("test_support") {
public_deps = [
":base",
":modular",
- ":release_channel_buildflags",
"//base",
"//net",
"//net:test_support",
@@ -120,6 +119,7 @@ source_set("test_support") {
test("cr_fuchsia_base_unittests") {
sources = [
"agent_impl_unittests.cc",
+ "inspect_unittest.cc",
"legacymetrics_client_unittest.cc",
"legacymetrics_histogram_flattener_unittest.cc",
"legacymetrics_user_event_recorder_unittest.cc",
@@ -132,6 +132,9 @@ test("cr_fuchsia_base_unittests") {
"//base:testfidl",
"//base/test:run_all_unittests",
"//base/test:test_support",
+ "//components/version_info",
"//testing/gtest",
+ "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
+ "//third_party/fuchsia-sdk/sdk/pkg/sys_inspect_cpp",
]
}
diff --git a/chromium/fuchsia/base/DEPS b/chromium/fuchsia/base/DEPS
index 9455f2ca503..5ded5f1b3d8 100644
--- a/chromium/fuchsia/base/DEPS
+++ b/chromium/fuchsia/base/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/version_info",
"+mojo/public",
"+third_party/blink/public/common/messaging",
"+third_party/blink/public/mojom/messaging",
diff --git a/chromium/fuchsia/base/agent_impl.cc b/chromium/fuchsia/base/agent_impl.cc
index b692599f2a2..4ecd277425e 100644
--- a/chromium/fuchsia/base/agent_impl.cc
+++ b/chromium/fuchsia/base/agent_impl.cc
@@ -7,7 +7,6 @@
#include <lib/sys/cpp/component_context.h>
#include "base/bind.h"
-#include "base/fuchsia/default_context.h"
namespace cr_fuchsia {
diff --git a/chromium/fuchsia/base/agent_impl.h b/chromium/fuchsia/base/agent_impl.h
index b630dc8bb6c..389efb30b28 100644
--- a/chromium/fuchsia/base/agent_impl.h
+++ b/chromium/fuchsia/base/agent_impl.h
@@ -15,7 +15,6 @@
#include "base/bind.h"
#include "base/containers/flat_map.h"
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/scoped_service_binding.h"
#include "base/fuchsia/service_provider_impl.h"
#include "base/macros.h"
diff --git a/chromium/fuchsia/base/agent_manager.h b/chromium/fuchsia/base/agent_manager.h
index 7f60750e471..17fd60c254c 100644
--- a/chromium/fuchsia/base/agent_manager.h
+++ b/chromium/fuchsia/base/agent_manager.h
@@ -10,7 +10,6 @@
#include <lib/sys/cpp/component_context.h>
#include "base/containers/flat_map.h"
-#include "base/fuchsia/default_context.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
diff --git a/chromium/fuchsia/base/config_reader.cc b/chromium/fuchsia/base/config_reader.cc
index 87eaab8e48c..0c73357e93a 100644
--- a/chromium/fuchsia/base/config_reader.cc
+++ b/chromium/fuchsia/base/config_reader.cc
@@ -29,14 +29,14 @@ base::Optional<base::Value> ReadPackageConfig() {
return base::nullopt;
}
- base::JSONReader reader;
- base::Optional<base::Value> parsed = reader.Read(file_content);
- CHECK(parsed) << "Failed to parse " << path.value() << ": "
- << reader.GetErrorMessage();
- CHECK(parsed->is_dict()) << "Config is not a JSON dictinary: "
- << path.value();
-
- return std::move(parsed.value());
+ base::JSONReader::ValueWithError parsed =
+ base::JSONReader::ReadAndReturnValueWithError(file_content);
+ CHECK(parsed.value) << "Failed to parse " << path.value() << ": "
+ << parsed.error_message;
+ CHECK(parsed.value->is_dict())
+ << "Config is not a JSON dictionary: " << path.value();
+
+ return std::move(parsed.value);
}
} // namespace
diff --git a/chromium/fuchsia/base/context_provider_test_connector.cc b/chromium/fuchsia/base/context_provider_test_connector.cc
index ba5f1234432..307f0bd9d0f 100644
--- a/chromium/fuchsia/base/context_provider_test_connector.cc
+++ b/chromium/fuchsia/base/context_provider_test_connector.cc
@@ -12,10 +12,8 @@
#include <zircon/processargs.h>
#include <utility>
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/fuchsia_logging.h"
-#include "base/strings/strcat.h"
-#include "fuchsia/base/release_channel.h"
+#include "base/fuchsia/process_context.h"
namespace cr_fuchsia {
@@ -24,9 +22,8 @@ fidl::InterfaceHandle<fuchsia::io::Directory> StartWebEngineForTests(
component_controller_request,
const base::CommandLine& command_line) {
fuchsia::sys::LaunchInfo launch_info;
- launch_info.url = base::StrCat({"fuchsia-pkg://fuchsia.com/web_engine",
- BUILDFLAG(FUCHSIA_RELEASE_CHANNEL_SUFFIX),
- "#meta/context_provider.cmx"});
+ launch_info.url =
+ "fuchsia-pkg://fuchsia.com/web_engine#meta/context_provider.cmx";
launch_info.arguments = command_line.argv();
// Clone stderr from the current process to WebEngine and ask it to
@@ -43,8 +40,7 @@ fidl::InterfaceHandle<fuchsia::io::Directory> StartWebEngineForTests(
web_engine_services_dir.NewRequest().TakeChannel();
fuchsia::sys::LauncherPtr launcher;
- base::fuchsia::ComponentContextForCurrentProcess()->svc()->Connect(
- launcher.NewRequest());
+ base::ComponentContextForProcess()->svc()->Connect(launcher.NewRequest());
launcher->CreateComponent(std::move(launch_info),
std::move(component_controller_request));
diff --git a/chromium/fuchsia/base/context_provider_test_connector.h b/chromium/fuchsia/base/context_provider_test_connector.h
index 0d5ca1fd707..5c4604b25bc 100644
--- a/chromium/fuchsia/base/context_provider_test_connector.h
+++ b/chromium/fuchsia/base/context_provider_test_connector.h
@@ -20,7 +20,6 @@ fidl::InterfaceHandle<fuchsia::io::Directory> StartWebEngineForTests(
const base::CommandLine& command_line =
base::CommandLine(base::CommandLine::NO_PROGRAM));
-// TODO(crbug.com/1046615): Use test manifests for package specification.
fuchsia::web::ContextProviderPtr ConnectContextProvider(
fidl::InterfaceRequest<fuchsia::sys::ComponentController>
component_controller_request,
diff --git a/chromium/fuchsia/base/feedback_registration.cc b/chromium/fuchsia/base/feedback_registration.cc
new file mode 100644
index 00000000000..d8bee5ff647
--- /dev/null
+++ b/chromium/fuchsia/base/feedback_registration.cc
@@ -0,0 +1,30 @@
+// 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/base/feedback_registration.h"
+
+#include <fuchsia/feedback/cpp/fidl.h>
+#include <lib/sys/cpp/component_context.h>
+
+#include "base/fuchsia/process_context.h"
+#include "base/strings/string_piece.h"
+#include "components/version_info/version_info.h"
+
+namespace cr_fuchsia {
+
+void RegisterCrashReportingFields(base::StringPiece component_url,
+ base::StringPiece crash_product_name) {
+ fuchsia::feedback::CrashReportingProduct product_data;
+ product_data.set_name(crash_product_name.as_string());
+ product_data.set_version(version_info::GetVersionNumber());
+ // TODO(https://crbug.com/1077428): Use the actual channel when appropriate.
+ // For now, always set it to the empty string to avoid reporting "missing".
+ product_data.set_channel("");
+ base::ComponentContextForProcess()
+ ->svc()
+ ->Connect<fuchsia::feedback::CrashReportingProductRegister>()
+ ->Upsert(component_url.as_string(), std::move(product_data));
+}
+
+} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/feedback_registration.h b/chromium/fuchsia/base/feedback_registration.h
new file mode 100644
index 00000000000..7e983bf6a70
--- /dev/null
+++ b/chromium/fuchsia/base/feedback_registration.h
@@ -0,0 +1,22 @@
+// 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_BASE_FEEDBACK_REGISTRATION_H_
+#define FUCHSIA_BASE_FEEDBACK_REGISTRATION_H_
+
+#include "base/strings/string_piece_forward.h"
+
+namespace cr_fuchsia {
+
+// Overrides the default Fuchsia product info in crash reports.
+// Crashes for the component |component_url| will contain |crash_product_name|,
+// the version from version_info, and an appropriate value for the release
+// channel. |component_url| must match the current component. The calling
+// process must have access to "fuchsia.feedback.CrashReportingProductRegister".
+void RegisterCrashReportingFields(base::StringPiece component_url,
+ base::StringPiece crash_product_name);
+
+} // namespace cr_fuchsia
+
+#endif // FUCHSIA_BASE_FEEDBACK_REGISTRATION_H_ \ No newline at end of file
diff --git a/chromium/fuchsia/base/frame_test_util.cc b/chromium/fuchsia/base/frame_test_util.cc
index c234b3a97fd..2150cd86360 100644
--- a/chromium/fuchsia/base/frame_test_util.cc
+++ b/chromium/fuchsia/base/frame_test_util.cc
@@ -54,4 +54,19 @@ fuchsia::web::LoadUrlParams CreateLoadUrlParamsWithUserActivation() {
return load_url_params;
}
+fuchsia::web::WebMessage CreateWebMessageWithMessagePortRequest(
+ fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request,
+ fuchsia::mem::Buffer buffer) {
+ fuchsia::web::OutgoingTransferable outgoing;
+ outgoing.set_message_port(std::move(message_port_request));
+
+ std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector;
+ outgoing_vector.push_back(std::move(outgoing));
+
+ fuchsia::web::WebMessage web_message;
+ web_message.set_outgoing_transfer(std::move(outgoing_vector));
+ web_message.set_data(std::move(buffer));
+ return web_message;
+}
+
} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/frame_test_util.h b/chromium/fuchsia/base/frame_test_util.h
index 2c2ee036456..20534eaf5e9 100644
--- a/chromium/fuchsia/base/frame_test_util.h
+++ b/chromium/fuchsia/base/frame_test_util.h
@@ -31,6 +31,12 @@ base::Optional<base::Value> ExecuteJavaScript(fuchsia::web::Frame* frame,
// autoplay to be used, which is used by many media tests.
fuchsia::web::LoadUrlParams CreateLoadUrlParamsWithUserActivation();
+// Creates a WebMessage with one outgoing transferable set to
+// |message_port_request| and data set to |buffer|.
+fuchsia::web::WebMessage CreateWebMessageWithMessagePortRequest(
+ fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request,
+ fuchsia::mem::Buffer buffer);
+
} // namespace cr_fuchsia
#endif // FUCHSIA_BASE_FRAME_TEST_UTIL_H_
diff --git a/chromium/fuchsia/base/inspect.cc b/chromium/fuchsia/base/inspect.cc
new file mode 100644
index 00000000000..775ae986618
--- /dev/null
+++ b/chromium/fuchsia/base/inspect.cc
@@ -0,0 +1,28 @@
+// 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/base/inspect.h"
+
+#include <lib/sys/inspect/cpp/component.h>
+
+#include "components/version_info/version_info.h"
+
+namespace cr_fuchsia {
+
+namespace {
+const char kVersion[] = "version";
+const char kLastChange[] = "last_change_revision";
+} // namespace
+
+void PublishVersionInfoToInspect(sys::ComponentInspector* inspector) {
+ // These values are managed by the inspector, since they won't be updated over
+ // the lifetime of the component.
+ // TODO(https://crbug.com/1077428): Add release channel.
+ inspector->root().CreateString(kVersion, version_info::GetVersionNumber(),
+ inspector);
+ inspector->root().CreateString(kLastChange, version_info::GetLastChange(),
+ inspector);
+}
+
+} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/inspect.h b/chromium/fuchsia/base/inspect.h
new file mode 100644
index 00000000000..4d8d35335ee
--- /dev/null
+++ b/chromium/fuchsia/base/inspect.h
@@ -0,0 +1,20 @@
+// 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_BASE_INSPECT_H_
+#define FUCHSIA_BASE_INSPECT_H_
+
+namespace sys {
+class ComponentInspector;
+} // namespace sys
+
+namespace cr_fuchsia {
+
+// Publish the Chromium version via the Inspect API. The lifetime of
+// |inspector| has to be the same as the component it belongs to.
+void PublishVersionInfoToInspect(sys::ComponentInspector* inspector);
+
+} // namespace cr_fuchsia
+
+#endif // FUCHSIA_BASE_INSPECT_H_ \ No newline at end of file
diff --git a/chromium/fuchsia/base/inspect_unittest.cc b/chromium/fuchsia/base/inspect_unittest.cc
new file mode 100644
index 00000000000..7a2bff50c81
--- /dev/null
+++ b/chromium/fuchsia/base/inspect_unittest.cc
@@ -0,0 +1,95 @@
+// 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/base/inspect.h"
+
+#include <lib/fdio/directory.h>
+#include <lib/inspect/cpp/hierarchy.h>
+#include <lib/inspect/cpp/reader.h>
+#include <lib/inspect/service/cpp/reader.h>
+#include <lib/sys/cpp/component_context.h>
+#include <lib/sys/inspect/cpp/component.h>
+#include <cstdint>
+#include <memory>
+
+#include "base/task/single_thread_task_executor.h"
+#include "base/test/task_environment.h"
+#include "components/version_info/version_info.h"
+#include "fuchsia/base/mem_buffer_util.h"
+#include "fuchsia/base/string_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cr_fuchsia {
+
+namespace {
+
+const char kVersion[] = "version";
+const char kLastChange[] = "last_change_revision";
+
+class InspectTest : public ::testing::Test {
+ public:
+ InspectTest() {
+ fidl::InterfaceHandle<fuchsia::io::Directory> incoming_directory;
+ auto incoming_services =
+ std::make_shared<sys::ServiceDirectory>(std::move(incoming_directory));
+ context_ = std::make_unique<sys::ComponentContext>(
+ std::move(incoming_services),
+ published_root_directory_.NewRequest().TakeChannel());
+ inspector_ = std::make_unique<sys::ComponentInspector>(context_.get());
+ base::RunLoop().RunUntilIdle();
+ }
+
+ InspectTest(const InspectTest&) = delete;
+ InspectTest& operator=(const InspectTest&) = delete;
+
+ protected:
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
+ std::unique_ptr<sys::ComponentContext> context_;
+ fidl::InterfaceHandle<fuchsia::io::Directory> published_root_directory_;
+ std::unique_ptr<sys::ComponentInspector> inspector_;
+};
+
+} // namespace
+
+TEST_F(InspectTest, PublishVersionInfoToInspect) {
+ cr_fuchsia::PublishVersionInfoToInspect(inspector_.get());
+ fidl::InterfaceHandle<fuchsia::io::Directory> directory;
+ zx_status_t status = fdio_service_connect_at(
+ published_root_directory_.channel().get(), "diagnostics",
+ directory.NewRequest().TakeChannel().release());
+ ASSERT_EQ(ZX_OK, status);
+ std::unique_ptr<sys::ServiceDirectory> diagnostics =
+ std::make_unique<sys::ServiceDirectory>(std::move(directory));
+
+ // Access the inspect::Tree where the data is served. |tree| is in the
+ // directory created for the test, not the diagnostics directory for the test
+ // component.
+ fuchsia::inspect::TreePtr tree;
+ diagnostics->Connect(tree.NewRequest());
+ fuchsia::inspect::TreeContent content;
+ base::RunLoop run_loop;
+ tree->GetContent([&content, &run_loop](fuchsia::inspect::TreeContent c) {
+ content = std::move(c);
+ run_loop.Quit();
+ });
+ run_loop.Run();
+
+ // Parse the data as an inspect::Hierarchy.
+ ASSERT_TRUE(content.has_buffer());
+ std::string buffer_data;
+ cr_fuchsia::StringFromMemBuffer(content.buffer(), &buffer_data);
+ inspect::Hierarchy hierarchy =
+ inspect::ReadFromBuffer(cr_fuchsia::StringToBytes(buffer_data))
+ .take_value();
+
+ auto* property =
+ hierarchy.node().get_property<inspect::StringPropertyValue>(kVersion);
+ EXPECT_EQ(property->value(), version_info::GetVersionNumber());
+ property =
+ hierarchy.node().get_property<inspect::StringPropertyValue>(kLastChange);
+ EXPECT_EQ(property->value(), version_info::GetLastChange());
+}
+
+} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/legacymetrics_client.cc b/chromium/fuchsia/base/legacymetrics_client.cc
index a2d45a83ac8..58f384124c1 100644
--- a/chromium/fuchsia/base/legacymetrics_client.cc
+++ b/chromium/fuchsia/base/legacymetrics_client.cc
@@ -11,8 +11,8 @@
#include <utility>
#include <vector>
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/fuchsia_logging.h"
+#include "base/fuchsia/process_context.h"
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -34,11 +34,13 @@ void LegacyMetricsClient::Start(base::TimeDelta report_interval) {
DCHECK(!metrics_recorder_) << "Start() called more than once.";
report_interval_ = report_interval;
- metrics_recorder_ = base::fuchsia::ComponentContextForCurrentProcess()
+ metrics_recorder_ = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::legacymetrics::MetricsRecorder>();
metrics_recorder_.set_error_handler(fit::bind_member(
this, &LegacyMetricsClient::OnMetricsRecorderDisconnected));
+ metrics_recorder_.events().OnCloseSoon =
+ fit::bind_member(this, &LegacyMetricsClient::OnCloseSoon);
user_events_recorder_ = std::make_unique<LegacyMetricsUserActionRecorder>();
ScheduleNextReport();
}
@@ -54,7 +56,18 @@ void LegacyMetricsClient::SetReportAdditionalMetricsCallback(
report_additional_callback_ = std::move(callback);
}
+void LegacyMetricsClient::SetNotifyFlushCallback(NotifyFlushCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+ DCHECK(!metrics_recorder_)
+ << "SetNotifyFlushCallback() must be called before Start().";
+
+ notify_flush_callback_ = std::move(callback);
+}
+
void LegacyMetricsClient::ScheduleNextReport() {
+ DCHECK(!is_flushing_);
+
DVLOG(1) << "Scheduling next report in " << report_interval_.InSeconds()
<< "seconds.";
timer_.Start(FROM_HERE, report_interval_, this,
@@ -91,44 +104,70 @@ void LegacyMetricsClient::Report(
}
}
- if (events.empty()) {
- ScheduleNextReport();
- return;
- }
+ std::move(events.begin(), events.end(), std::back_inserter(to_send_));
- DrainBuffer(std::move(events));
+ DrainBuffer();
}
-void LegacyMetricsClient::DrainBuffer(
- std::vector<fuchsia::legacymetrics::Event> buffer) {
- if (buffer.empty()) {
+void LegacyMetricsClient::DrainBuffer() {
+ DVLOG(1) << __func__ << " called.";
+
+ if (record_ack_pending_) {
+ // There is a Record() call already inflight. When it is acknowledged,
+ // buffer draining will continue.
+ return;
+ }
+
+ if (to_send_.empty()) {
DVLOG(1) << "Buffer drained.";
- ScheduleNextReport();
+
+ if (is_flushing_) {
+ metrics_recorder_.Unbind();
+ } else {
+ ScheduleNextReport();
+ }
+
return;
}
- // Since ordering doesn't matter, we can efficiently drain |buffer| by
+ // Since ordering doesn't matter, we can efficiently drain |to_send_| by
// repeatedly sending and truncating its tail.
- const size_t batch_size = std::min(buffer.size(), kMaxBatchSize);
- const size_t batch_start_idx = buffer.size() - batch_size;
+ const size_t batch_size = std::min(to_send_.size(), kMaxBatchSize);
+ const size_t batch_start_idx = to_send_.size() - batch_size;
std::vector<fuchsia::legacymetrics::Event> batch;
batch.resize(batch_size);
- std::move(buffer.begin() + batch_start_idx, buffer.end(), batch.begin());
- buffer.resize(buffer.size() - batch_size);
-
- metrics_recorder_->Record(std::move(batch),
- [this, buffer = std::move(buffer)]() mutable {
- DrainBuffer(std::move(buffer));
- });
+ std::move(to_send_.begin() + batch_start_idx, to_send_.end(), batch.begin());
+ to_send_.resize(to_send_.size() - batch_size);
+
+ record_ack_pending_ = true;
+ metrics_recorder_->Record(std::move(batch), [this]() {
+ record_ack_pending_ = false;
+ DrainBuffer();
+ });
}
void LegacyMetricsClient::OnMetricsRecorderDisconnected(zx_status_t status) {
- ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status)
- << "MetricsRecorder connection lost.";
+ ZX_LOG(ERROR, status) << "MetricsRecorder connection lost.";
// Stop recording & reporting user events.
user_events_recorder_.reset();
timer_.AbandonAndStop();
}
+void LegacyMetricsClient::OnCloseSoon() {
+ DVLOG(1) << __func__ << " called.";
+
+ timer_.AbandonAndStop();
+
+ is_flushing_ = true;
+ if (notify_flush_callback_) {
+ // Defer reporting until the flush operation has finished.
+ std::move(notify_flush_callback_)
+ .Run(base::BindOnce(&LegacyMetricsClient::StartReport,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ StartReport();
+ }
+}
+
} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/legacymetrics_client.h b/chromium/fuchsia/base/legacymetrics_client.h
index 98576a1f410..b9ec76a2a1f 100644
--- a/chromium/fuchsia/base/legacymetrics_client.h
+++ b/chromium/fuchsia/base/legacymetrics_client.h
@@ -31,6 +31,8 @@ class LegacyMetricsClient {
using ReportAdditionalMetricsCallback = base::RepeatingCallback<void(
base::OnceCallback<void(std::vector<fuchsia::legacymetrics::Event>)>)>;
+ using NotifyFlushCallback =
+ base::OnceCallback<void(base::OnceClosure completion_cb)>;
LegacyMetricsClient();
~LegacyMetricsClient();
@@ -50,18 +52,27 @@ class LegacyMetricsClient {
void SetReportAdditionalMetricsCallback(
ReportAdditionalMetricsCallback callback);
+ // Sets a |callback| which is invoked to warn that the connection to the
+ // remote MetricsRecorder will be terminated. The completion closure passed to
+ // |callback| should be invoked to signal flush completion.
+ void SetNotifyFlushCallback(NotifyFlushCallback callback);
+
private:
void ScheduleNextReport();
void StartReport();
void Report(std::vector<fuchsia::legacymetrics::Event> additional_metrics);
void OnMetricsRecorderDisconnected(zx_status_t status);
+ void OnCloseSoon();
- // Incrementally sends the contents of |buffer| to |metrics_recorder|, and
- // invokes |done_cb| when finished.
- void DrainBuffer(std::vector<fuchsia::legacymetrics::Event> buffer);
+ // Incrementally sends the contents of |to_send_| to |metrics_recorder_|.
+ void DrainBuffer();
base::TimeDelta report_interval_;
ReportAdditionalMetricsCallback report_additional_callback_;
+ NotifyFlushCallback notify_flush_callback_;
+ bool is_flushing_ = false;
+ bool record_ack_pending_ = false;
+ std::vector<fuchsia::legacymetrics::Event> to_send_;
std::unique_ptr<LegacyMetricsUserActionRecorder> user_events_recorder_;
fuchsia::legacymetrics::MetricsRecorderPtr metrics_recorder_;
diff --git a/chromium/fuchsia/base/legacymetrics_client_unittest.cc b/chromium/fuchsia/base/legacymetrics_client_unittest.cc
index 8c735bbbffe..1b48827418a 100644
--- a/chromium/fuchsia/base/legacymetrics_client_unittest.cc
+++ b/chromium/fuchsia/base/legacymetrics_client_unittest.cc
@@ -14,6 +14,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "fuchsia/base/legacymetrics_client.h"
#include "fuchsia/base/legacymetrics_histogram_flattener.h"
+#include "fuchsia/base/result_receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cr_fuchsia {
@@ -45,10 +46,21 @@ class TestMetricsRecorder
ack_callback_ = base::nullopt;
}
+ void set_expect_ack_dropped(bool expect_dropped) {
+ expect_ack_dropped_ = expect_dropped;
+ }
+
// fuchsia::legacymetrics::MetricsRecorder implementation.
void Record(std::vector<fuchsia::legacymetrics::Event> events,
RecordCallback callback) override {
- recorded_events_ = std::move(events);
+ std::move(events.begin(), events.end(),
+ std::back_inserter(recorded_events_));
+
+ // Received a call to Record() before the previous one was acknowledged,
+ // which can happen in some cases (e.g. flushing).
+ if (ack_callback_)
+ EXPECT_TRUE(expect_ack_dropped_);
+
ack_callback_ = std::move(callback);
if (on_record_cb_)
@@ -61,6 +73,7 @@ class TestMetricsRecorder
std::vector<fuchsia::legacymetrics::Event> recorded_events_;
base::OnceClosure on_record_cb_;
base::Optional<RecordCallback> ack_callback_;
+ bool expect_ack_dropped_ = false;
};
class LegacyMetricsClientTest : public testing::Test {
@@ -71,9 +84,10 @@ class LegacyMetricsClientTest : public testing::Test {
~LegacyMetricsClientTest() override = default;
void SetUp() override {
- service_binding_ = std::make_unique<base::fuchsia::ScopedServiceBinding<
- fuchsia::legacymetrics::MetricsRecorder>>(
- test_context_.additional_services(), &test_recorder_);
+ service_binding_ =
+ std::make_unique<base::fuchsia::ScopedSingleClientServiceBinding<
+ fuchsia::legacymetrics::MetricsRecorder>>(
+ test_context_.additional_services(), &test_recorder_);
base::SetRecordActionTaskRunner(base::ThreadTaskRunnerHandle::Get());
// Flush any dirty histograms from previous test runs in this process.
@@ -84,7 +98,7 @@ class LegacyMetricsClientTest : public testing::Test {
base::test::TaskEnvironment task_environment_;
base::TestComponentContextForProcess test_context_;
TestMetricsRecorder test_recorder_;
- std::unique_ptr<base::fuchsia::ScopedServiceBinding<
+ std::unique_ptr<base::fuchsia::ScopedSingleClientServiceBinding<
fuchsia::legacymetrics::MetricsRecorder>>
service_binding_;
LegacyMetricsClient client_;
@@ -216,5 +230,92 @@ TEST_F(LegacyMetricsClientTest, Batching) {
test_recorder_.SendAck();
}
+TEST_F(LegacyMetricsClientTest, FlushWithPending) {
+ client_.Start(kReportInterval);
+ base::RunLoop().RunUntilIdle();
+
+ UMA_HISTOGRAM_COUNTS_1M("foo", 20);
+
+ EXPECT_FALSE(test_recorder_.IsRecordInFlight());
+ service_binding_->events().OnCloseSoon();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(test_recorder_.IsRecordInFlight());
+
+ // The service should be unbound once all data is drained.
+ EXPECT_TRUE(service_binding_->has_clients());
+ auto events = test_recorder_.WaitForEvents();
+ test_recorder_.SendAck();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1u, events.size());
+ EXPECT_EQ("foo", events[0].histogram().name());
+ EXPECT_FALSE(service_binding_->has_clients());
+}
+
+TEST_F(LegacyMetricsClientTest, FlushNoData) {
+ client_.Start(kReportInterval);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(service_binding_->has_clients());
+ EXPECT_FALSE(test_recorder_.IsRecordInFlight());
+ service_binding_->events().OnCloseSoon();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(service_binding_->has_clients());
+}
+
+TEST_F(LegacyMetricsClientTest, FlushWithOutstandingAck) {
+ client_.Start(kReportInterval);
+ base::RunLoop().RunUntilIdle();
+
+ // Send "foo", but don't ack.
+ UMA_HISTOGRAM_COUNTS_1M("foo", 20);
+ task_environment_.FastForwardBy(kReportInterval);
+ EXPECT_TRUE(test_recorder_.IsRecordInFlight());
+
+ // Allow the flush operation to call Record() without waiting for a prior ack.
+ test_recorder_.set_expect_ack_dropped(true);
+
+ // Buffer another event and trigger a flush.
+ UMA_HISTOGRAM_COUNTS_1M("bar", 20);
+ EXPECT_TRUE(service_binding_->has_clients());
+ service_binding_->events().OnCloseSoon();
+
+ // Simulate an asynchronous ack from the recorder, which be delivered around
+ // the same time as the flush's Record() call. The ack should be gracefully
+ // ignored by the client.
+ test_recorder_.SendAck();
+
+ base::RunLoop().RunUntilIdle();
+
+ auto events = test_recorder_.WaitForEvents();
+ test_recorder_.SendAck();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(2u, events.size());
+ EXPECT_EQ("foo", events[0].histogram().name());
+ EXPECT_EQ("bar", events[1].histogram().name());
+ EXPECT_FALSE(service_binding_->has_clients());
+}
+
+TEST_F(LegacyMetricsClientTest, ExternalFlushSignal) {
+ ResultReceiver<base::OnceClosure> flush_receiver;
+ client_.SetNotifyFlushCallback(flush_receiver.GetReceiveCallback());
+ client_.Start(kReportInterval);
+ base::RunLoop().RunUntilIdle();
+
+ UMA_HISTOGRAM_COUNTS_1M("foo", 20);
+
+ // Verify that reporting does not start until the flush completion callback is
+ // run.
+ EXPECT_FALSE(test_recorder_.IsRecordInFlight());
+ service_binding_->events().OnCloseSoon();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(test_recorder_.IsRecordInFlight());
+
+ // Verify that invoking the completion callback unblocks reporting.
+ EXPECT_TRUE(flush_receiver.has_value());
+ std::move(*flush_receiver).Run();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(test_recorder_.IsRecordInFlight());
+}
+
} // namespace
} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/legacymetrics_histogram_flattener.cc b/chromium/fuchsia/base/legacymetrics_histogram_flattener.cc
index e05d87ced9a..b6d728143c1 100644
--- a/chromium/fuchsia/base/legacymetrics_histogram_flattener.cc
+++ b/chromium/fuchsia/base/legacymetrics_histogram_flattener.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "base/logging.h"
#include "base/metrics/statistics_recorder.h"
namespace cr_fuchsia {
diff --git a/chromium/fuchsia/cast_streaming/BUILD.gn b/chromium/fuchsia/cast_streaming/BUILD.gn
index c691165e93d..94d567cc610 100644
--- a/chromium/fuchsia/cast_streaming/BUILD.gn
+++ b/chromium/fuchsia/cast_streaming/BUILD.gn
@@ -11,16 +11,23 @@ source_set("cast_streaming") {
"//components/openscreen_platform:openscreen_platform_network_service",
"//fuchsia/base",
"//media",
+ "//media/mojo/common",
+ "//media/mojo/mojom",
+ "//mojo/public/cpp/system",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.web",
"//third_party/openscreen/src/cast/streaming:receiver",
"//third_party/openscreen/src/platform:api",
"//third_party/openscreen/src/util",
]
visibility = [ "//fuchsia/engine/*" ]
- public = [ "public/cast_streaming_session.h" ]
+ public = [
+ "public/cast_streaming.h",
+ "public/cast_streaming_session.h",
+ ]
sources = [
"cast_message_port_impl.cc",
"cast_message_port_impl.h",
+ "cast_streaming.cc",
"cast_streaming_session.cc",
"stream_consumer.cc",
"stream_consumer.h",
diff --git a/chromium/fuchsia/cast_streaming/DEPS b/chromium/fuchsia/cast_streaming/DEPS
index 13d521158c3..5208c523d56 100644
--- a/chromium/fuchsia/cast_streaming/DEPS
+++ b/chromium/fuchsia/cast_streaming/DEPS
@@ -1,5 +1,7 @@
include_rules = [
"+components/openscreen_platform",
"+media/base",
+ "+media/mojo",
+ "+mojo/public",
"+third_party/openscreen/src",
]
diff --git a/chromium/fuchsia/cast_streaming/cast_streaming.cc b/chromium/fuchsia/cast_streaming/cast_streaming.cc
new file mode 100644
index 00000000000..2044900b05b
--- /dev/null
+++ b/chromium/fuchsia/cast_streaming/cast_streaming.cc
@@ -0,0 +1,24 @@
+// 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/cast_streaming/public/cast_streaming.h"
+
+#include "base/strings/string_piece.h"
+
+namespace cast_streaming {
+
+bool IsCastStreamingAppOrigin(base::StringPiece origin) {
+ constexpr char kCastStreamingMessagePortOrigin[] = "cast-streaming:receiver";
+ return origin == kCastStreamingMessagePortOrigin;
+}
+
+bool IsValidCastStreamingMessage(const fuchsia::web::WebMessage& message) {
+ // |message| should contain exactly one OutgoingTransferrable, with a single
+ // MessagePort.
+ return message.has_outgoing_transfer() &&
+ message.outgoing_transfer().size() == 1u &&
+ message.outgoing_transfer()[0].is_message_port();
+}
+
+} // namespace cast_streaming
diff --git a/chromium/fuchsia/cast_streaming/cast_streaming_session.cc b/chromium/fuchsia/cast_streaming/cast_streaming_session.cc
index 71f931737bc..565df0defae 100644
--- a/chromium/fuchsia/cast_streaming/cast_streaming_session.cc
+++ b/chromium/fuchsia/cast_streaming/cast_streaming_session.cc
@@ -8,11 +8,14 @@
#include "base/bind.h"
#include "base/notreached.h"
+#include "components/openscreen_platform/network_context.h"
#include "components/openscreen_platform/network_util.h"
#include "components/openscreen_platform/task_runner.h"
#include "fuchsia/cast_streaming/cast_message_port_impl.h"
#include "fuchsia/cast_streaming/stream_consumer.h"
#include "media/base/media_util.h"
+#include "media/mojo/common/mojo_decoder_buffer_converter.h"
+#include "mojo/public/cpp/system/data_pipe.h"
#include "third_party/openscreen/src/cast/streaming/receiver.h"
#include "third_party/openscreen/src/cast/streaming/receiver_session.h"
@@ -27,6 +30,12 @@ constexpr char kVideoCodecVp8[] = "vp8";
namespace cast_streaming {
+// static
+void CastStreamingSession::SetNetworkContextGetter(
+ NetworkContextGetter getter) {
+ openscreen_platform::SetNetworkContextGetter(std::move(getter));
+}
+
// Owns the Open Screen ReceiverSession. The Cast Streaming Session is tied to
// the lifespan of this object.
class CastStreamingSession::Internal
@@ -37,12 +46,9 @@ class CastStreamingSession::Internal
fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request,
scoped_refptr<base::SequencedTaskRunner> task_runner)
: task_runner_(task_runner),
- environment_(&openscreen::Clock::now,
- &task_runner_,
- openscreen::IPEndpoint{
- openscreen::IPAddress(0, 0, 0, 0, 0, 0, 0, 0), 0}),
+ environment_(&openscreen::Clock::now, &task_runner_),
cast_message_port_impl_(std::move(message_port_request)),
- // TODO(crbug.com/1042501): Add streaming session Constraints and
+ // TODO(crbug.com/1087520): Add streaming session Constraints and
// DisplayDescription.
receiver_session_(
this,
@@ -73,14 +79,31 @@ class CastStreamingSession::Internal
DVLOG(1) << __func__;
DCHECK_EQ(session, &receiver_session_);
- base::Optional<media::AudioDecoderConfig> audio_decoder_config;
+ base::Optional<AudioStreamInfo> audio_stream_info;
if (receivers.audio) {
+ // Creare the audio data pipe.
+ const MojoCreateDataPipeOptions data_pipe_options{
+ sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE,
+ 1u /* element_num_bytes */,
+ media::GetDefaultDecoderBufferConverterCapacity(
+ media::DemuxerStream::Type::AUDIO)};
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ MojoResult result = mojo::CreateDataPipe(
+ &data_pipe_options, &data_pipe_producer, &data_pipe_consumer);
+ if (result != MOJO_RESULT_OK) {
+ client_->OnInitializationFailure();
+ return;
+ }
+
+ // Initialize the audio consumer.
audio_consumer_ = std::make_unique<StreamConsumer>(
- receivers.audio->receiver,
+ receivers.audio->receiver, std::move(data_pipe_producer),
base::BindRepeating(
- &CastStreamingSession::Client::OnAudioFrameReceived,
+ &CastStreamingSession::Client::OnAudioBufferReceived,
base::Unretained(client_)));
+ // Gather data for the audio decoder config.
media::ChannelLayout channel_layout =
media::GuessChannelLayout(receivers.audio->receiver_config.channels);
const std::string& audio_codec =
@@ -89,22 +112,42 @@ class CastStreamingSession::Internal
media::StringToAudioCodec(audio_codec);
int samples_per_second = receivers.audio->receiver_config.rtp_timebase;
- audio_decoder_config.emplace(media::AudioDecoderConfig(
- media_audio_codec, media::SampleFormat::kSampleFormatF32,
- channel_layout, samples_per_second, media::EmptyExtraData(),
- media::EncryptionScheme::kUnencrypted));
+ audio_stream_info.emplace(AudioStreamInfo{
+ media::AudioDecoderConfig(
+ media_audio_codec, media::SampleFormat::kSampleFormatF32,
+ channel_layout, samples_per_second, media::EmptyExtraData(),
+ media::EncryptionScheme::kUnencrypted),
+ std::move(data_pipe_consumer)});
- DVLOG(1) << "Initialized audio stream using " << audio_codec << " codec.";
+ DVLOG(1) << "Initialized audio stream. "
+ << audio_stream_info->decoder_config.AsHumanReadableString();
}
- base::Optional<media::VideoDecoderConfig> video_decoder_config;
+ base::Optional<VideoStreamInfo> video_stream_info;
if (receivers.video) {
+ // Creare the video data pipe.
+ const MojoCreateDataPipeOptions data_pipe_options{
+ sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE,
+ 1u /* element_num_bytes */,
+ media::GetDefaultDecoderBufferConverterCapacity(
+ media::DemuxerStream::Type::VIDEO)};
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ MojoResult result = mojo::CreateDataPipe(
+ &data_pipe_options, &data_pipe_producer, &data_pipe_consumer);
+ if (result != MOJO_RESULT_OK) {
+ client_->OnInitializationFailure();
+ return;
+ }
+
+ // Initialize the video consumer.
video_consumer_ = std::make_unique<StreamConsumer>(
- receivers.video->receiver,
+ receivers.video->receiver, std::move(data_pipe_producer),
base::BindRepeating(
- &CastStreamingSession::Client::OnVideoFrameReceived,
+ &CastStreamingSession::Client::OnVideoBufferReceived,
base::Unretained(client_)));
+ // Gather data for the video decoder config.
const std::string& video_codec =
receivers.video->selected_stream.stream.codec_name;
uint32_t video_width =
@@ -114,36 +157,39 @@ class CastStreamingSession::Internal
gfx::Size video_size(video_width, video_height);
gfx::Rect video_rect(video_width, video_height);
+ media::VideoCodec media_video_codec =
+ media::VideoCodec::kUnknownVideoCodec;
+ media::VideoCodecProfile video_codec_profile =
+ media::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN;
+
if (video_codec == kVideoCodecH264) {
- video_decoder_config.emplace(media::VideoDecoderConfig(
- media::VideoCodec::kCodecH264,
- media::VideoCodecProfile::H264PROFILE_BASELINE,
- media::VideoDecoderConfig::AlphaMode::kIsOpaque,
- media::VideoColorSpace(), media::VideoTransformation(), video_size,
- video_rect, video_size, media::EmptyExtraData(),
- media::EncryptionScheme::kUnencrypted));
+ media_video_codec = media::VideoCodec::kCodecH264;
+ video_codec_profile = media::VideoCodecProfile::H264PROFILE_BASELINE;
} else if (video_codec == kVideoCodecVp8) {
- video_decoder_config.emplace(media::VideoDecoderConfig(
- media::VideoCodec::kCodecVP8,
- media::VideoCodecProfile::VP8PROFILE_MIN,
- media::VideoDecoderConfig::AlphaMode::kIsOpaque,
- media::VideoColorSpace(), media::VideoTransformation(), video_size,
- video_rect, video_size, media::EmptyExtraData(),
- media::EncryptionScheme::kUnencrypted));
+ media_video_codec = media::VideoCodec::kCodecVP8;
+ video_codec_profile = media::VideoCodecProfile::VP8PROFILE_MIN;
} else {
NOTREACHED();
}
- DVLOG(1) << "Initialized video stream of " << video_width << "x"
- << video_height << " resolution using " << video_codec
- << " codec.";
+ video_stream_info.emplace(VideoStreamInfo{
+ media::VideoDecoderConfig(
+ media_video_codec, video_codec_profile,
+ media::VideoDecoderConfig::AlphaMode::kIsOpaque,
+ media::VideoColorSpace(), media::VideoTransformation(),
+ video_size, video_rect, video_size, media::EmptyExtraData(),
+ media::EncryptionScheme::kUnencrypted),
+ std::move(data_pipe_consumer)});
+
+ DVLOG(1) << "Initialized video stream. "
+ << video_stream_info->decoder_config.AsHumanReadableString();
}
- if (!video_decoder_config && !audio_decoder_config) {
+ if (!audio_stream_info && !video_stream_info) {
client_->OnInitializationFailure();
} else {
- client_->OnInitializationSuccess(std::move(audio_decoder_config),
- std::move(video_decoder_config));
+ client_->OnInitializationSuccess(std::move(audio_stream_info),
+ std::move(video_stream_info));
}
initialized_called_ = true;
}
@@ -192,4 +238,9 @@ void CastStreamingSession::Start(
client, std::move(message_port_request), task_runner);
}
+void CastStreamingSession::Stop() {
+ DCHECK(internal_);
+ internal_.reset();
+}
+
} // namespace cast_streaming
diff --git a/chromium/fuchsia/cast_streaming/public/cast_streaming.h b/chromium/fuchsia/cast_streaming/public/cast_streaming.h
new file mode 100644
index 00000000000..0838317b6ac
--- /dev/null
+++ b/chromium/fuchsia/cast_streaming/public/cast_streaming.h
@@ -0,0 +1,25 @@
+// 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_CAST_STREAMING_PUBLIC_CAST_STREAMING_H_
+#define FUCHSIA_CAST_STREAMING_PUBLIC_CAST_STREAMING_H_
+
+#include <fuchsia/web/cpp/fidl.h>
+
+#include "base/strings/string_piece_forward.h"
+
+namespace cast_streaming {
+
+// TODO(crbug.com/1082821): Remove this file once the Cast Streaming Receiver is
+// implemented as a separate component from WebEngine.
+
+// Returns true if |origin| is the Cast Streaming MessagePort origin.
+bool IsCastStreamingAppOrigin(base::StringPiece origin);
+
+// Returns true if |message| contains a valid Cast Streaming Message.
+bool IsValidCastStreamingMessage(const fuchsia::web::WebMessage& message);
+
+} // namespace cast_streaming
+
+#endif // FUCHSIA_CAST_STREAMING_PUBLIC_CAST_STREAMING_H_
diff --git a/chromium/fuchsia/cast_streaming/public/cast_streaming_session.h b/chromium/fuchsia/cast_streaming/public/cast_streaming_session.h
index 6769ba1b49f..bb6703989c7 100644
--- a/chromium/fuchsia/cast_streaming/public/cast_streaming_session.h
+++ b/chromium/fuchsia/cast_streaming/public/cast_streaming_session.h
@@ -9,11 +9,19 @@
#include <fuchsia/web/cpp/fidl.h>
+#include "base/callback.h"
#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "media/base/audio_decoder_config.h"
-#include "media/base/decoder_buffer.h"
#include "media/base/video_decoder_config.h"
+#include "media/mojo/mojom/media_types.mojom.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+
+namespace network {
+namespace mojom {
+class NetworkContext;
+} // namespace mojom
+} // namespace network
namespace cast_streaming {
@@ -21,25 +29,44 @@ namespace cast_streaming {
// Cast Streaming Session for a provided FIDL MessagePort request.
class CastStreamingSession {
public:
+ using NetworkContextGetter =
+ base::RepeatingCallback<network::mojom::NetworkContext*()>;
+
+ // Sets the NetworkContextGetter. This must be called before any call to
+ // Start() and must only be called once. If the NetworkContext crashes, any
+ // existing Cast Streaming Session will eventually terminate and call
+ // OnReceiverSessionEnded().
+ static void SetNetworkContextGetter(NetworkContextGetter getter);
+
+ template <class T>
+ struct StreamInfo {
+ T decoder_config;
+ mojo::ScopedDataPipeConsumerHandle data_pipe;
+ };
+ using AudioStreamInfo = StreamInfo<media::AudioDecoderConfig>;
+ using VideoStreamInfo = StreamInfo<media::VideoDecoderConfig>;
+
class Client {
public:
// Called when the Cast Streaming Session has been successfully initialized.
- // It is guaranteed that at least one of |audio_decoder_config| or
- // |video_decoder_config| will be set.
+ // It is guaranteed that at least one of |audio_stream_info| or
+ // |video_stream_info| will be set.
virtual void OnInitializationSuccess(
- base::Optional<media::AudioDecoderConfig> audio_decoder_config,
- base::Optional<media::VideoDecoderConfig> video_decoder_config) = 0;
+ base::Optional<AudioStreamInfo> audio_stream_info,
+ base::Optional<VideoStreamInfo> video_stream_info) = 0;
// Called when the Cast Stream Session failed to initialize.
virtual void OnInitializationFailure() = 0;
- // Called on every new audio frame after OnInitializationSuccess().
- virtual void OnAudioFrameReceived(
- scoped_refptr<media::DecoderBuffer> buffer) = 0;
+ // Called on every new audio buffer after OnInitializationSuccess(). The
+ // frame data must be accessed via the |data_pipe| property in StreamInfo.
+ virtual void OnAudioBufferReceived(
+ media::mojom::DecoderBufferPtr buffer) = 0;
- // Called on every new video frame after OnInitializationSuccess().
- virtual void OnVideoFrameReceived(
- scoped_refptr<media::DecoderBuffer> buffer) = 0;
+ // Called on every new video buffer after OnInitializationSuccess(). The
+ // frame data must be accessed via the |data_pipe| property in StreamInfo.
+ virtual void OnVideoBufferReceived(
+ media::mojom::DecoderBufferPtr buffer) = 0;
// Called when the Cast Streaming Session has ended.
virtual void OnReceiverSessionEnded() = 0;
@@ -66,6 +93,10 @@ class CastStreamingSession {
fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request,
scoped_refptr<base::SequencedTaskRunner> task_runner);
+ // Stops the Cast Streaming Session. This can only be called once during the
+ // lifespan of this object and only after a call to Start().
+ void Stop();
+
private:
class Internal;
std::unique_ptr<Internal> internal_;
diff --git a/chromium/fuchsia/cast_streaming/stream_consumer.cc b/chromium/fuchsia/cast_streaming/stream_consumer.cc
index bcfb8a4d6b1..353ac52119a 100644
--- a/chromium/fuchsia/cast_streaming/stream_consumer.cc
+++ b/chromium/fuchsia/cast_streaming/stream_consumer.cc
@@ -5,27 +5,132 @@
#include "fuchsia/cast_streaming/stream_consumer.h"
#include "base/logging.h"
+#include "base/time/time.h"
+#include "media/base/media_util.h"
namespace cast_streaming {
StreamConsumer::StreamConsumer(openscreen::cast::Receiver* receiver,
+ mojo::ScopedDataPipeProducerHandle data_pipe,
FrameReceivedCB frame_received_cb)
- : receiver_(receiver), frame_received_cb_(std::move(frame_received_cb)) {
+ : receiver_(receiver),
+ data_pipe_(std::move(data_pipe)),
+ frame_received_cb_(std::move(frame_received_cb)),
+ pipe_watcher_(FROM_HERE,
+ mojo::SimpleWatcher::ArmingPolicy::MANUAL,
+ base::SequencedTaskRunnerHandle::Get()) {
DCHECK(receiver_);
receiver_->SetConsumer(this);
+ MojoResult result =
+ pipe_watcher_.Watch(data_pipe_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
+ base::BindRepeating(&StreamConsumer::OnPipeWritable,
+ base::Unretained(this)));
+ if (result != MOJO_RESULT_OK) {
+ CloseDataPipeOnError();
+ }
}
StreamConsumer::~StreamConsumer() {
receiver_->SetConsumer(nullptr);
}
+void StreamConsumer::CloseDataPipeOnError() {
+ DLOG(WARNING) << "[ssrc:" << receiver_->ssrc() << "] Data pipe closed.";
+ receiver_->SetConsumer(nullptr);
+ pipe_watcher_.Cancel();
+ data_pipe_.reset();
+}
+
+void StreamConsumer::OnPipeWritable(MojoResult result) {
+ DCHECK(data_pipe_);
+
+ if (result != MOJO_RESULT_OK) {
+ CloseDataPipeOnError();
+ return;
+ }
+
+ uint32_t bytes_written = pending_buffer_remaining_bytes_;
+ result = data_pipe_->WriteData(pending_buffer_ + pending_buffer_offset_,
+ &bytes_written, MOJO_WRITE_DATA_FLAG_NONE);
+ if (result != MOJO_RESULT_OK) {
+ CloseDataPipeOnError();
+ return;
+ }
+
+ pending_buffer_offset_ += bytes_written;
+ pending_buffer_remaining_bytes_ -= bytes_written;
+ if (pending_buffer_remaining_bytes_ != 0) {
+ pipe_watcher_.ArmOrNotify();
+ return;
+ }
+
+ // Advance to the next frame if a new one is ready.
+ int next_frame_buffer_size = receiver_->AdvanceToNextFrame();
+ if (next_frame_buffer_size != openscreen::cast::Receiver::kNoFramesReady)
+ OnFramesReady(next_frame_buffer_size);
+}
+
void StreamConsumer::OnFramesReady(int next_frame_buffer_size) {
- // TODO(crbug.com/1042501): Do not allocate a buffer for every new frame, use
- // a buffer pool.
- std::unique_ptr<uint8_t[]> buffer =
- std::make_unique<uint8_t[]>(next_frame_buffer_size);
- openscreen::cast::EncodedFrame encoded_frame = receiver_->ConsumeNextFrame(
- absl::Span<uint8_t>(buffer.get(), next_frame_buffer_size));
+ DCHECK(data_pipe_);
+
+ if (pending_buffer_remaining_bytes_ != 0) {
+ // There already is a pending frame. Ignore this one for now.
+ return;
+ }
+
+ void* buffer = nullptr;
+ uint32_t buffer_size = next_frame_buffer_size;
+ uint32_t mojo_buffer_size = next_frame_buffer_size;
+
+ if (buffer_size > kMaxFrameSize) {
+ LOG(ERROR) << "[ssrc:" << receiver_->ssrc() << "] "
+ << "Frame size too big: " << buffer_size;
+ CloseDataPipeOnError();
+ return;
+ }
+
+ MojoResult result = data_pipe_->BeginWriteData(
+ &buffer, &mojo_buffer_size, MOJO_BEGIN_WRITE_DATA_FLAG_NONE);
+
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ pipe_watcher_.ArmOrNotify();
+ return;
+ }
+
+ if (result != MOJO_RESULT_OK) {
+ CloseDataPipeOnError();
+ return;
+ }
+
+ openscreen::cast::EncodedFrame encoded_frame;
+ size_t bytes_written = 0;
+
+ if (mojo_buffer_size < buffer_size) {
+ DVLOG(2) << "[ssrc:" << receiver_->ssrc() << "] "
+ << "Mojo data pipe full";
+
+ // The |data_pipe_| buffer cannot take the full frame, write to
+ // |pending_buffer_| instead.
+ encoded_frame = receiver_->ConsumeNextFrame(
+ absl::Span<uint8_t>(pending_buffer_, buffer_size));
+
+ // Write as much as we can to the |data_pipe_| buffer.
+ memcpy(buffer, pending_buffer_, mojo_buffer_size);
+ pending_buffer_offset_ = mojo_buffer_size;
+ pending_buffer_remaining_bytes_ = buffer_size - mojo_buffer_size;
+ bytes_written = mojo_buffer_size;
+ } else {
+ // Write directly to the |data_pipe_| buffer.
+ encoded_frame = receiver_->ConsumeNextFrame(
+ absl::Span<uint8_t>(static_cast<uint8_t*>(buffer), buffer_size));
+ bytes_written = buffer_size;
+ }
+
+ result = data_pipe_->EndWriteData(bytes_written);
+ if (result != MOJO_RESULT_OK) {
+ CloseDataPipeOnError();
+ return;
+ }
const bool is_key_frame =
encoded_frame.dependency ==
@@ -37,26 +142,21 @@ void StreamConsumer::OnFramesReady(int next_frame_buffer_size) {
receiver_->rtp_timebase())
.count());
- DVLOG(3) << "[ssrc:" << receiver_->ssrc()
- << "] Received new frame. Timestamp: " << playout_time
+ DVLOG(3) << "[ssrc:" << receiver_->ssrc() << "] "
+ << "Received new frame. Timestamp: " << playout_time
<< ", is_key_frame: " << is_key_frame;
- if (playout_time <= last_playout_time_) {
- // TODO(b/156129097): We sometimes receive identical playout time for two
- // frames in a row.
- DVLOG(2) << "[ssrc:" << receiver_->ssrc()
- << "] Droped frame due to identical playout time.";
- return;
- }
- last_playout_time_ = playout_time;
+ frame_received_cb_.Run(media::mojom::DecoderBuffer::New(
+ playout_time /* timestamp */, base::TimeDelta() /* duration */,
+ false /* is_end_of_stream */, buffer_size, is_key_frame,
+ media::EmptyExtraData(), media::mojom::DecryptConfigPtr(),
+ base::TimeDelta() /* front_discard */,
+ base::TimeDelta() /* back_discard */
+ ));
- scoped_refptr<media::DecoderBuffer> decoder_buffer =
- media::DecoderBuffer::FromArray(std::move(buffer),
- next_frame_buffer_size);
- decoder_buffer->set_is_key_frame(is_key_frame);
- decoder_buffer->set_timestamp(playout_time);
-
- frame_received_cb_.Run(decoder_buffer);
+ if (pending_buffer_remaining_bytes_ != 0) {
+ pipe_watcher_.ArmOrNotify();
+ }
}
} // namespace cast_streaming
diff --git a/chromium/fuchsia/cast_streaming/stream_consumer.h b/chromium/fuchsia/cast_streaming/stream_consumer.h
index 4605d158bde..eef5f14b1a7 100644
--- a/chromium/fuchsia/cast_streaming/stream_consumer.h
+++ b/chromium/fuchsia/cast_streaming/stream_consumer.h
@@ -8,23 +8,33 @@
#include <fuchsia/media/cpp/fidl.h>
#include "base/callback.h"
-#include "base/time/time.h"
-#include "media/base/decoder_buffer.h"
+#include "media/mojo/mojom/media_types.mojom.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
#include "third_party/openscreen/src/cast/streaming/receiver.h"
#include "third_party/openscreen/src/cast/streaming/receiver_session.h"
namespace cast_streaming {
-// Attaches to an Open Screen Receiver to receive frames and invokes
-// |frame_received_cb_| with each received buffer of encoded data.
+// Attaches to an Open Screen Receiver to receive buffers of encoded data and
+// invokes |frame_received_cb_| with each buffer.
+//
+// Internally, this class writes buffers of encoded data directly to
+// |data_pipe_| rather than using a helper class like MojoDecoderBufferWriter.
+// This allows us to use |data_pipe_| as an end-to-end buffer to cap memory
+// usage. Receiving new buffers is delayed until the pipe has free memory again.
+// The Open Screen library takes care of discarding buffers that are too old and
+// requesting new key frames as needed.
class StreamConsumer : public openscreen::cast::Receiver::Consumer {
public:
using FrameReceivedCB =
- base::RepeatingCallback<void(scoped_refptr<media::DecoderBuffer>)>;
+ base::RepeatingCallback<void(media::mojom::DecoderBufferPtr)>;
// |receiver| sends frames to this object. It must outlive this object.
- // |frame_received_cb| is called on every new frame.
+ // |frame_received_cb| is called on every new frame, after a new frame has
+ // been written to |data_pipe|. On error, |data_pipe| will be closed.
StreamConsumer(openscreen::cast::Receiver* receiver,
+ mojo::ScopedDataPipeProducerHandle data_pipe,
FrameReceivedCB frame_received_cb);
~StreamConsumer() final;
@@ -32,12 +42,34 @@ class StreamConsumer : public openscreen::cast::Receiver::Consumer {
StreamConsumer& operator=(const StreamConsumer&) = delete;
private:
+ // Maximum frame size that OnFramesReady() can accept.
+ static constexpr uint32_t kMaxFrameSize = 512 * 1024;
+
+ // Closes |data_pipe_| and resets the Consumer in |receiver_|. No frames will
+ // be received after this call.
+ void CloseDataPipeOnError();
+
+ // Callback when |data_pipe_| can be written to again after it was full.
+ void OnPipeWritable(MojoResult result);
+
// openscreen::cast::Receiver::Consumer implementation.
void OnFramesReady(int next_frame_buffer_size) final;
openscreen::cast::Receiver* const receiver_;
+ mojo::ScopedDataPipeProducerHandle data_pipe_;
const FrameReceivedCB frame_received_cb_;
- base::TimeDelta last_playout_time_;
+
+ // Provides notifications about |data_pipe_| readiness.
+ mojo::SimpleWatcher pipe_watcher_;
+
+ // Buffer used when |data_pipe_| is too full to accept the next frame size.
+ uint8_t pending_buffer_[kMaxFrameSize];
+
+ // Current offset for data |pending_buffer_| to be written to |data_pipe_|.
+ size_t pending_buffer_offset_ = 0;
+
+ // Remaining bytes to write from |pending_buffer_| to |data_pipe_|.
+ size_t pending_buffer_remaining_bytes_ = 0;
};
} // namespace cast_streaming
diff --git a/chromium/fuchsia/cipd/BUILD.gn b/chromium/fuchsia/cipd/BUILD.gn
index 22d726631ad..a59fd83d727 100644
--- a/chromium/fuchsia/cipd/BUILD.gn
+++ b/chromium/fuchsia/cipd/BUILD.gn
@@ -124,6 +124,17 @@ cipd_archive("http") {
sources = [ "${root_gen_dir}/fuchsia/http/http/http.far" ]
}
+cipd_archive("web_engine_shell") {
+ package_definition_yaml = "web_engine_shell.yaml"
+ package = "chromium/fuchsia/web_engine_shell-\${targetarch}"
+ description = "Simple command-line embedder for WebEngine."
+
+ deps = [ "//fuchsia/engine:web_engine_shell_pkg" ]
+
+ sources =
+ [ "${root_gen_dir}/fuchsia/engine/web_engine_shell/web_engine_shell.far" ]
+}
+
_stripped_chromedriver_file = "${root_out_dir}/clang_x64/stripped/chromedriver"
action("strip_chromedriver_binary") {
@@ -249,6 +260,7 @@ group("cipd") {
":debug_symbols",
":http",
":tests",
+ ":web_engine_shell",
":webrunner",
]
}
diff --git a/chromium/fuchsia/engine/BUILD.gn b/chromium/fuchsia/engine/BUILD.gn
index 59e33cedeac..fe80aee12ce 100644
--- a/chromium/fuchsia/engine/BUILD.gn
+++ b/chromium/fuchsia/engine/BUILD.gn
@@ -6,7 +6,6 @@ assert(is_fuchsia)
import("//build/config/fuchsia/generate_runner_scripts.gni")
import("//build/config/fuchsia/symbol_archive.gni")
-import("//fuchsia/release_channel.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//testing/test.gni")
import("//tools/grit/repack.gni")
@@ -28,10 +27,12 @@ declare_args() {
mojom("mojom") {
sources = [
+ "cast_streaming_session.mojom",
"on_load_script_injector.mojom",
"url_request_rewrite.mojom",
]
public_deps = [
+ "//media/mojo/mojom",
"//mojo/public/mojom/base",
"//services/network/public/mojom",
]
@@ -106,6 +107,7 @@ component("web_engine_core") {
"//media",
"//media/fuchsia/cdm/service",
"//media/fuchsia/mojom",
+ "//media/mojo/common",
"//media/mojo/services",
"//mojo/public/cpp/bindings",
"//services/media_session/public/mojom",
@@ -145,6 +147,8 @@ component("web_engine_core") {
"browser/accessibility_bridge.h",
"browser/ax_tree_converter.cc",
"browser/ax_tree_converter.h",
+ "browser/cast_streaming_session_client.cc",
+ "browser/cast_streaming_session_client.h",
"browser/content_directory_loader_factory.cc",
"browser/content_directory_loader_factory.h",
"browser/context_impl.cc",
@@ -185,6 +189,8 @@ component("web_engine_core") {
"browser/web_engine_net_log_observer.h",
"browser/web_engine_permission_delegate.cc",
"browser/web_engine_permission_delegate.h",
+ "common/cast_streaming.cc",
+ "common/cast_streaming.h",
"common/cors_exempt_headers.cc",
"common/cors_exempt_headers.h",
"common/web_engine_content_client.cc",
@@ -195,12 +201,18 @@ component("web_engine_core") {
"context_provider_impl.h",
"context_provider_main.cc",
"context_provider_main.h",
+ "renderer/cast_streaming_demuxer.cc",
+ "renderer/cast_streaming_demuxer.h",
+ "renderer/cast_streaming_receiver.cc",
+ "renderer/cast_streaming_receiver.h",
"renderer/on_load_script_injector.cc",
"renderer/on_load_script_injector.h",
"renderer/url_request_rules_receiver.cc",
"renderer/url_request_rules_receiver.h",
"renderer/web_engine_content_renderer_client.cc",
"renderer/web_engine_content_renderer_client.h",
+ "renderer/web_engine_render_frame_observer.cc",
+ "renderer/web_engine_render_frame_observer.h",
"renderer/web_engine_url_loader_throttle_provider.cc",
"renderer/web_engine_url_loader_throttle_provider.h",
"url_request_rewrite_type_converters.cc",
@@ -234,8 +246,6 @@ cr_fuchsia_package("web_engine") {
binary = ":web_engine_exe"
manifest = "context_provider.cmx"
component_name_override = "context_provider"
- package_name_override = "web_engine${release_channel_suffix}"
- archive_name_override = "web_engine"
excluded_files = [
"lib/libswiftshader_libEGL.so",
@@ -272,6 +282,7 @@ source_set("browsertest_core") {
test("web_engine_browsertests") {
sources = [
"browser/accessibility_bridge_browsertest.cc",
+ "browser/cast_streaming_browsertest.cc",
"browser/content_directory_browsertest.cc",
"browser/context_impl_browsertest.cc",
"browser/frame_impl_browsertest.cc",
@@ -381,7 +392,6 @@ executable("web_engine_shell_exec") {
deps = [
"//base",
"//fuchsia/base",
- "//fuchsia/base:release_channel_buildflags",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.policy",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.web",
"//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp",
diff --git a/chromium/fuchsia/engine/DEPS b/chromium/fuchsia/engine/DEPS
index b074327e28e..048342eb9f5 100644
--- a/chromium/fuchsia/engine/DEPS
+++ b/chromium/fuchsia/engine/DEPS
@@ -10,6 +10,7 @@ include_rules = [
"+media/fuchsia",
"+mojo/public",
"+services/service_manager",
+ "+third_party/blink/public/common/switches.h",
"+third_party/widevine/cdm/widevine_cdm_common.h",
"+ui/base",
"+ui/gfx",
diff --git a/chromium/fuchsia/engine/OWNERS b/chromium/fuchsia/engine/OWNERS
index 7b7d0cfbd65..b9be02c3f28 100644
--- a/chromium/fuchsia/engine/OWNERS
+++ b/chromium/fuchsia/engine/OWNERS
@@ -10,3 +10,5 @@ per-file web_engine_browser_interface_binders.*=file://ipc/SECURITY_OWNERS
# For sandbox security review.
per-file context_provider_impl.*=set noparent
per-file context_provider_impl.*=file://fuchsia/SECURITY_OWNERS
+per-file *.cmx=set noparent
+per-file *.cmx=file://fuchsia/SECURITY_OWNERS
diff --git a/chromium/fuchsia/engine/browser/DEPS b/chromium/fuchsia/engine/browser/DEPS
index 79f6dcab122..6ffa902e765 100644
--- a/chromium/fuchsia/engine/browser/DEPS
+++ b/chromium/fuchsia/engine/browser/DEPS
@@ -6,6 +6,8 @@ include_rules = [
"+media/capabilities",
"+media/fuchsia/cdm/service",
"+media/fuchsia/mojom",
+ "+media/mojo/common",
+ "+media/mojo/mojom",
"+media/mojo/services",
"+mojo/public/cpp/bindings",
"+mojo/public/cpp/system",
diff --git a/chromium/fuchsia/engine/browser/accessibility_bridge_browsertest.cc b/chromium/fuchsia/engine/browser/accessibility_bridge_browsertest.cc
index 0d97daf24e1..6476e8a0f28 100644
--- a/chromium/fuchsia/engine/browser/accessibility_bridge_browsertest.cc
+++ b/chromium/fuchsia/engine/browser/accessibility_bridge_browsertest.cc
@@ -4,13 +4,11 @@
#include <fuchsia/accessibility/semantics/cpp/fidl.h>
#include <fuchsia/accessibility/semantics/cpp/fidl_test_base.h>
-#include <lib/sys/cpp/component_context.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <zircon/types.h>
#include "base/auto_reset.h"
#include "base/check.h"
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/scoped_service_binding.h"
#include "base/notreached.h"
#include "base/test/bind_test_util.h"
diff --git a/chromium/fuchsia/engine/browser/cast_streaming_browsertest.cc b/chromium/fuchsia/engine/browser/cast_streaming_browsertest.cc
new file mode 100644
index 00000000000..cc94207a341
--- /dev/null
+++ b/chromium/fuchsia/engine/browser/cast_streaming_browsertest.cc
@@ -0,0 +1,129 @@
+// 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 "content/public/test/browser_test.h"
+#include "fuchsia/base/fit_adapter.h"
+#include "fuchsia/base/frame_test_util.h"
+#include "fuchsia/base/mem_buffer_util.h"
+#include "fuchsia/base/result_receiver.h"
+#include "fuchsia/base/test_navigation_listener.h"
+#include "fuchsia/engine/browser/frame_impl.h"
+#include "fuchsia/engine/switches.h"
+#include "fuchsia/engine/test/test_data.h"
+#include "fuchsia/engine/test/web_engine_browser_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kCastStreamingReceiverPath[] = "/cast_streaming_receiver.html";
+
+} // namespace
+
+// Base test fixture for Cast Streaming tests.
+class CastStreamingBaseTest : public cr_fuchsia::WebEngineBrowserTest {
+ public:
+ CastStreamingBaseTest() {
+ set_test_server_root(base::FilePath(cr_fuchsia::kTestServerRoot));
+ }
+ ~CastStreamingBaseTest() override = default;
+
+ CastStreamingBaseTest(const CastStreamingBaseTest&) = delete;
+ CastStreamingBaseTest& operator=(const CastStreamingBaseTest&) = delete;
+
+ protected:
+ // Creates a Frame with |navigation_listener_| attached.
+ fuchsia::web::FramePtr CreateFrame() {
+ return WebEngineBrowserTest::CreateFrame(&navigation_listener_);
+ }
+
+ cr_fuchsia::TestNavigationListener navigation_listener_;
+};
+
+// Test fixture for Cast Streaming tests with the Cast Streaming Receiver flag
+// disabled.
+class CastStreamingDisabledTest : public CastStreamingBaseTest {
+ public:
+ CastStreamingDisabledTest() = default;
+ ~CastStreamingDisabledTest() override = default;
+ CastStreamingDisabledTest(const CastStreamingDisabledTest&) = delete;
+ CastStreamingDisabledTest& operator=(const CastStreamingDisabledTest&) =
+ delete;
+
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ content::BrowserTestBase::SetUpCommandLine(command_line);
+ command_line->RemoveSwitch(switches::kEnableCastStreamingReceiver);
+ }
+};
+
+// Test fixture for Cast Streaming tests with the Cast Streaming Receiver flag
+// enabled.
+class CastStreamingTest : public CastStreamingBaseTest {
+ public:
+ CastStreamingTest() = default;
+ ~CastStreamingTest() override = default;
+ CastStreamingTest(const CastStreamingTest&) = delete;
+ CastStreamingTest& operator=(const CastStreamingTest&) = delete;
+
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ content::BrowserTestBase::SetUpCommandLine(command_line);
+ command_line->AppendSwitch(switches::kEnableCastStreamingReceiver);
+ }
+};
+
+// Check that attempting to load the cast streaming media source URL when the
+// command line switch is not set fails as expected.
+IN_PROC_BROWSER_TEST_F(CastStreamingDisabledTest, LoadFailure) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL page_url(embedded_test_server()->GetURL(kCastStreamingReceiverPath));
+
+ fuchsia::web::FramePtr frame = CreateFrame();
+ fuchsia::web::NavigationControllerPtr controller;
+ frame->GetNavigationController(controller.NewRequest());
+ EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
+ controller.get(), fuchsia::web::LoadUrlParams(), page_url.spec()));
+ navigation_listener_.RunUntilTitleEquals("error");
+}
+
+// Check that the Cast Streaming MessagePort gets properly set on the Frame.
+IN_PROC_BROWSER_TEST_F(CastStreamingTest, FrameMessagePort) {
+ fuchsia::web::FramePtr frame = CreateFrame();
+
+ FrameImpl* frame_impl = context_impl()->GetFrameImplForTest(&frame);
+ ASSERT_TRUE(frame_impl);
+ EXPECT_FALSE(frame_impl->cast_streaming_session_client_for_test());
+
+ fuchsia::web::MessagePortPtr cast_streaming_message_port;
+
+ base::RunLoop run_loop;
+ cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result>
+ post_result(run_loop.QuitClosure());
+ frame->PostMessage(
+ "cast-streaming:receiver",
+ cr_fuchsia::CreateWebMessageWithMessagePortRequest(
+ cast_streaming_message_port.NewRequest(),
+ cr_fuchsia::MemBufferFromString("hi", "test")),
+ cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
+ run_loop.Run();
+ ASSERT_TRUE(post_result->is_response());
+
+ EXPECT_TRUE(frame_impl->cast_streaming_session_client_for_test());
+}
+
+// Check that attempting to load the cast streaming media source URL when the
+// command line switch is set properly succeeds.
+// TODO(crbug.com/1087537): Re-enable when we have a test implementation for a
+// Cast Streaming Sender.
+IN_PROC_BROWSER_TEST_F(CastStreamingTest, DISABLED_LoadSuccess) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL page_url(embedded_test_server()->GetURL(kCastStreamingReceiverPath));
+
+ fuchsia::web::FramePtr frame = CreateFrame();
+ fuchsia::web::NavigationControllerPtr controller;
+ frame->GetNavigationController(controller.NewRequest());
+ EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
+ controller.get(), fuchsia::web::LoadUrlParams(), page_url.spec()));
+ navigation_listener_.RunUntilTitleEquals("canplay");
+}
diff --git a/chromium/fuchsia/engine/browser/cast_streaming_session_client.cc b/chromium/fuchsia/engine/browser/cast_streaming_session_client.cc
new file mode 100644
index 00000000000..5b022f927eb
--- /dev/null
+++ b/chromium/fuchsia/engine/browser/cast_streaming_session_client.cc
@@ -0,0 +1,111 @@
+// 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/engine/browser/cast_streaming_session_client.h"
+
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/video_decoder_config.h"
+#include "media/mojo/mojom/media_types.mojom.h"
+
+CastStreamingSessionClient::CastStreamingSessionClient(
+ fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request)
+ : message_port_request_(std::move(message_port_request)) {}
+
+CastStreamingSessionClient::~CastStreamingSessionClient() = default;
+
+void CastStreamingSessionClient::StartMojoConnection(
+ mojo::AssociatedRemote<mojom::CastStreamingReceiver>
+ cast_streaming_receiver) {
+ DVLOG(1) << __func__;
+ cast_streaming_receiver_ = std::move(cast_streaming_receiver);
+
+ // It is fine to use an unretained pointer to |this| here as the
+ // AssociatedRemote, is owned by |this| and will be torn-down at the same time
+ // as |this|.
+ cast_streaming_receiver_->EnableReceiver(base::BindOnce(
+ &CastStreamingSessionClient::OnReceiverEnabled, base::Unretained(this)));
+ cast_streaming_receiver_.set_disconnect_handler(base::BindOnce(
+ &CastStreamingSessionClient::OnMojoDisconnect, base::Unretained(this)));
+}
+
+void CastStreamingSessionClient::OnReceiverEnabled() {
+ DVLOG(1) << __func__;
+ DCHECK(message_port_request_);
+ cast_streaming_session_.Start(this, std::move(message_port_request_),
+ base::SequencedTaskRunnerHandle::Get());
+}
+
+void CastStreamingSessionClient::OnInitializationSuccess(
+ base::Optional<cast_streaming::CastStreamingSession::AudioStreamInfo>
+ audio_stream_info,
+ base::Optional<cast_streaming::CastStreamingSession::VideoStreamInfo>
+ video_stream_info) {
+ DVLOG(1) << __func__;
+ DCHECK(audio_stream_info || video_stream_info);
+
+ mojom::AudioStreamInfoPtr mojo_audio_stream_info;
+ if (audio_stream_info) {
+ mojo_audio_stream_info =
+ mojom::AudioStreamInfo::New(audio_stream_info->decoder_config,
+ audio_remote_.BindNewPipeAndPassReceiver(),
+ std::move(audio_stream_info->data_pipe));
+ }
+
+ mojom::VideoStreamInfoPtr mojo_video_stream_info;
+ if (video_stream_info) {
+ mojo_video_stream_info =
+ mojom::VideoStreamInfo::New(video_stream_info->decoder_config,
+ video_remote_.BindNewPipeAndPassReceiver(),
+ std::move(video_stream_info->data_pipe));
+ }
+
+ cast_streaming_receiver_->OnStreamsInitialized(
+ std::move(mojo_audio_stream_info), std::move(mojo_video_stream_info));
+}
+
+void CastStreamingSessionClient::OnInitializationFailure() {
+ DVLOG(1) << __func__;
+ cast_streaming_receiver_.reset();
+}
+
+void CastStreamingSessionClient::OnAudioBufferReceived(
+ media::mojom::DecoderBufferPtr buffer) {
+ DVLOG(3) << __func__;
+ DCHECK(audio_remote_);
+ audio_remote_->ProvideBuffer(std::move(buffer));
+}
+
+void CastStreamingSessionClient::OnVideoBufferReceived(
+ media::mojom::DecoderBufferPtr buffer) {
+ DVLOG(3) << __func__;
+ DCHECK(video_remote_);
+ video_remote_->ProvideBuffer(std::move(buffer));
+}
+
+void CastStreamingSessionClient::OnReceiverSessionEnded() {
+ DVLOG(1) << __func__;
+
+ // Tear down the Mojo connection.
+ cast_streaming_receiver_.reset();
+}
+
+void CastStreamingSessionClient::OnMojoDisconnect() {
+ DVLOG(1) << __func__;
+
+ if (message_port_request_) {
+ // Close the MessagePort if the Cast Streaming Session was never started.
+ message_port_request_.Close(ZX_ERR_PEER_CLOSED);
+ cast_streaming_receiver_.reset();
+ return;
+ }
+
+ // Close the Cast Streaming Session. This will eventually call
+ // OnReceiverSessionEnded(), which will tear down the Mojo connection.
+ cast_streaming_session_.Stop();
+
+ // Tear down all remaining Mojo objects.
+ audio_remote_.reset();
+ video_remote_.reset();
+}
diff --git a/chromium/fuchsia/engine/browser/cast_streaming_session_client.h b/chromium/fuchsia/engine/browser/cast_streaming_session_client.h
new file mode 100644
index 00000000000..f502a77e9b6
--- /dev/null
+++ b/chromium/fuchsia/engine/browser/cast_streaming_session_client.h
@@ -0,0 +1,57 @@
+// 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_ENGINE_BROWSER_CAST_STREAMING_SESSION_CLIENT_H_
+#define FUCHSIA_ENGINE_BROWSER_CAST_STREAMING_SESSION_CLIENT_H_
+
+#include <fuchsia/web/cpp/fidl.h>
+
+#include "fuchsia/cast_streaming/public/cast_streaming_session.h"
+#include "fuchsia/engine/cast_streaming_session.mojom.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+// Owns the CastStreamingSession and sends buffers to the renderer process via
+// a Mojo service.
+class CastStreamingSessionClient
+ : public cast_streaming::CastStreamingSession::Client {
+ public:
+ explicit CastStreamingSessionClient(
+ fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request);
+ ~CastStreamingSessionClient() final;
+
+ CastStreamingSessionClient(const CastStreamingSessionClient&) = delete;
+ CastStreamingSessionClient& operator=(const CastStreamingSessionClient&) =
+ delete;
+
+ void StartMojoConnection(mojo::AssociatedRemote<mojom::CastStreamingReceiver>
+ cast_streaming_receiver);
+
+ private:
+ // Handler for |cast_streaming_receiver_| disconnect.
+ void OnMojoDisconnect();
+
+ // Callback for mojom::CastStreamingReceiver::EnableReceiver()
+ void OnReceiverEnabled();
+
+ // cast_streaming::CastStreamingSession::Client implementation.
+ void OnInitializationSuccess(
+ base::Optional<cast_streaming::CastStreamingSession::AudioStreamInfo>
+ audio_stream_info,
+ base::Optional<cast_streaming::CastStreamingSession::VideoStreamInfo>
+ video_stream_info) final;
+ void OnInitializationFailure() final;
+ void OnAudioBufferReceived(media::mojom::DecoderBufferPtr buffer) final;
+ void OnVideoBufferReceived(media::mojom::DecoderBufferPtr buffer) final;
+ void OnReceiverSessionEnded() final;
+
+ fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request_;
+ mojo::AssociatedRemote<mojom::CastStreamingReceiver> cast_streaming_receiver_;
+ cast_streaming::CastStreamingSession cast_streaming_session_;
+
+ mojo::Remote<mojom::CastStreamingBufferReceiver> audio_remote_;
+ mojo::Remote<mojom::CastStreamingBufferReceiver> video_remote_;
+};
+
+#endif // FUCHSIA_ENGINE_BROWSER_CAST_STREAMING_SESSION_CLIENT_H_
diff --git a/chromium/fuchsia/engine/browser/context_impl.cc b/chromium/fuchsia/engine/browser/context_impl.cc
index 6c8d4641fb9..d7a12f55e7c 100644
--- a/chromium/fuchsia/engine/browser/context_impl.cc
+++ b/chromium/fuchsia/engine/browser/context_impl.cc
@@ -11,8 +11,10 @@
#include "base/bind.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
+#include "fuchsia/cast_streaming/public/cast_streaming_session.h"
#include "fuchsia/engine/browser/frame_impl.h"
#include "fuchsia/engine/browser/web_engine_devtools_controller.h"
@@ -27,6 +29,10 @@ ContextImpl::ContextImpl(content::BrowserContext* browser_context,
DCHECK(browser_context_);
DCHECK(devtools_controller_);
devtools_controller_->OnContextCreated();
+
+ cast_streaming::CastStreamingSession::SetNetworkContextGetter(
+ base::BindRepeating(&ContextImpl::GetNetworkContext,
+ base::Unretained(this)));
}
ContextImpl::~ContextImpl() {
@@ -130,3 +136,9 @@ FrameImpl* ContextImpl::GetFrameImplForTest(
return nullptr;
}
+
+network::mojom::NetworkContext* ContextImpl::GetNetworkContext() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ return content::BrowserContext::GetDefaultStoragePartition(browser_context_)
+ ->GetNetworkContext();
+}
diff --git a/chromium/fuchsia/engine/browser/context_impl.h b/chromium/fuchsia/engine/browser/context_impl.h
index 48ee4a49b9a..53b4218a0b8 100644
--- a/chromium/fuchsia/engine/browser/context_impl.h
+++ b/chromium/fuchsia/engine/browser/context_impl.h
@@ -20,6 +20,12 @@ class BrowserContext;
class WebContents;
} // namespace content
+namespace network {
+namespace mojom {
+class NetworkContext;
+} // namespace mojom
+} // namespace network
+
class FrameImpl;
class WebEngineDevToolsController;
@@ -68,6 +74,9 @@ class WEB_ENGINE_EXPORT ContextImpl : public fuchsia::web::Context {
}
private:
+ // Returns the NetworkContext from the default StoragePartition.
+ network::mojom::NetworkContext* GetNetworkContext();
+
// Reference to the browser implementation for this Context.
content::BrowserContext* const browser_context_;
diff --git a/chromium/fuchsia/engine/browser/cookie_manager_impl.cc b/chromium/fuchsia/engine/browser/cookie_manager_impl.cc
index e7362ae5618..d5c05f4e74b 100644
--- a/chromium/fuchsia/engine/browser/cookie_manager_impl.cc
+++ b/chromium/fuchsia/engine/browser/cookie_manager_impl.cc
@@ -67,12 +67,13 @@ class CookiesIteratorImpl : public fuchsia::web::CookiesIterator,
}
// Same as above except it takes CookieStatusList instead of just CookieList.
CookiesIteratorImpl(
- const std::vector<net::CookieWithStatus>& cookies_with_statuses,
+ const std::vector<net::CookieWithAccessResult>&
+ cookies_with_access_results,
fidl::InterfaceRequest<fuchsia::web::CookiesIterator> iterator)
: CookiesIteratorImpl(std::move(iterator)) {
- for (const auto& cookie_with_status : cookies_with_statuses) {
- queued_cookies_[cookie_with_status.cookie.UniqueKey()] =
- ConvertCanonicalCookie(cookie_with_status.cookie,
+ for (const auto& cookie_with_access_result : cookies_with_access_results) {
+ queued_cookies_[cookie_with_access_result.cookie.UniqueKey()] =
+ ConvertCanonicalCookie(cookie_with_access_result.cookie,
net::CookieChangeCause::INSERTED);
}
}
@@ -159,12 +160,12 @@ void OnAllCookiesReceived(
void OnCookiesAndExcludedReceived(
fidl::InterfaceRequest<fuchsia::web::CookiesIterator> iterator,
- const std::vector<net::CookieWithStatus>& cookies_with_statuses,
- const std::vector<net::CookieWithStatus>& excluded_cookies) {
+ const std::vector<net::CookieWithAccessResult>& cookies_with_access_results,
+ const std::vector<net::CookieWithAccessResult>& excluded_cookies) {
// Since CookieOptions::set_return_excluded_cookies() is not used when calling
// the Mojo GetCookieList() API, |excluded_cookies| should be empty.
DCHECK(excluded_cookies.empty());
- new CookiesIteratorImpl(cookies_with_statuses, std::move(iterator));
+ new CookiesIteratorImpl(cookies_with_access_results, std::move(iterator));
}
} // namespace
diff --git a/chromium/fuchsia/engine/browser/cookie_manager_impl_unittest.cc b/chromium/fuchsia/engine/browser/cookie_manager_impl_unittest.cc
index 93f28165f04..d756548fe92 100644
--- a/chromium/fuchsia/engine/browser/cookie_manager_impl_unittest.cc
+++ b/chromium/fuchsia/engine/browser/cookie_manager_impl_unittest.cc
@@ -17,6 +17,7 @@
#include "fuchsia/base/result_receiver.h"
#include "fuchsia/engine/browser/cookie_manager_impl.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "net/cookies/cookie_inclusion_status.h"
#include "services/network/network_service.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
@@ -74,7 +75,7 @@ class CookieManagerImplTest : public testing::Test {
net::CookieOptions options;
mojo_cookie_manager_->SetCanonicalCookie(
*CreateCookie(name, value), GURL(kTestCookieUrl), options,
- base::BindOnce([](net::CanonicalCookie::CookieInclusionStatus status) {
+ base::BindOnce([](net::CookieInclusionStatus status) {
EXPECT_TRUE(status.IsInclude());
}));
}
diff --git a/chromium/fuchsia/engine/browser/event_filter.cc b/chromium/fuchsia/engine/browser/event_filter.cc
index 2a9351273bf..7ad83ac534e 100644
--- a/chromium/fuchsia/engine/browser/event_filter.cc
+++ b/chromium/fuchsia/engine/browser/event_filter.cc
@@ -6,6 +6,7 @@
#include <limits>
+#include "base/notreached.h"
#include "ui/events/event.h"
namespace {
diff --git a/chromium/fuchsia/engine/browser/frame_impl.cc b/chromium/fuchsia/engine/browser/frame_impl.cc
index 6f9df2f15e3..317166e3c60 100644
--- a/chromium/fuchsia/engine/browser/frame_impl.cc
+++ b/chromium/fuchsia/engine/browser/frame_impl.cc
@@ -6,16 +6,16 @@
#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h>
+#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <limits>
#include "base/bind_helpers.h"
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/fuchsia_logging.h"
+#include "base/fuchsia/process_context.h"
#include "base/json/json_writer.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
@@ -34,13 +34,16 @@
#include "content/public/common/was_activated_option.mojom.h"
#include "fuchsia/base/mem_buffer_util.h"
#include "fuchsia/base/message_port.h"
+#include "fuchsia/cast_streaming/public/cast_streaming.h"
#include "fuchsia/engine/browser/accessibility_bridge.h"
+#include "fuchsia/engine/browser/cast_streaming_session_client.h"
#include "fuchsia/engine/browser/context_impl.h"
#include "fuchsia/engine/browser/event_filter.h"
#include "fuchsia/engine/browser/frame_layout_manager.h"
#include "fuchsia/engine/browser/frame_window_tree_host.h"
#include "fuchsia/engine/browser/media_player_impl.h"
#include "fuchsia/engine/browser/web_engine_devtools_controller.h"
+#include "fuchsia/engine/common/cast_streaming.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "net/base/net_errors.h"
@@ -475,8 +478,8 @@ void FrameImpl::DestroyWindowTreeHost() {
// Allows posted focus events to process before the FocusController is torn
// down.
- base::DeleteSoon(FROM_HERE, {content::BrowserThread::UI},
- std::move(focus_controller_));
+ content::GetUIThreadTaskRunner({})->DeleteSoon(FROM_HERE,
+ std::move(focus_controller_));
}
void FrameImpl::CloseAndDestroyFrame(zx_status_t error) {
@@ -495,7 +498,81 @@ void FrameImpl::OnMediaPlayerDisconnect() {
media_player_ = nullptr;
}
+bool FrameImpl::MaybeHandleCastStreamingMessage(
+ std::string* origin,
+ fuchsia::web::WebMessage* message,
+ PostMessageCallback* callback) {
+ if (!IsCastStreamingEnabled())
+ return false;
+
+ if (!cast_streaming::IsCastStreamingAppOrigin(*origin))
+ return false;
+
+ fuchsia::web::Frame_PostMessage_Result result;
+ if (cast_streaming_session_client_ ||
+ !cast_streaming::IsValidCastStreamingMessage(*message)) {
+ // The Cast Streaming MessagePort should only be set once and |message|
+ // should be a valid Cast Streaming Message.
+ result.set_err(fuchsia::web::FrameError::INVALID_ORIGIN);
+ (*callback)(std::move(result));
+ return true;
+ }
+
+ cast_streaming_session_client_ = std::make_unique<CastStreamingSessionClient>(
+ std::move((*message->mutable_outgoing_transfer())[0].message_port()));
+ result.set_response(fuchsia::web::Frame_PostMessage_Response());
+ (*callback)(std::move(result));
+ return true;
+}
+
+void FrameImpl::MaybeInjectBeforeLoadScripts(
+ content::NavigationHandle* navigation_handle) {
+ if (before_load_scripts_.empty())
+ return;
+
+ mojo::AssociatedRemote<mojom::OnLoadScriptInjector>
+ before_load_script_injector;
+ navigation_handle->GetRenderFrameHost()
+ ->GetRemoteAssociatedInterfaces()
+ ->GetInterface(&before_load_script_injector);
+
+ // Provision the renderer's ScriptInjector with the scripts scoped to this
+ // page's origin.
+ before_load_script_injector->ClearOnLoadScripts();
+ for (uint64_t script_id : before_load_scripts_order_) {
+ const OriginScopedScript& script = before_load_scripts_[script_id];
+ if (IsOriginWhitelisted(navigation_handle->GetURL(), script.origins())) {
+ // TODO(crbug.com/1060846): Stop using handle<shared_buffer>.
+ before_load_script_injector->AddOnLoadScript(
+ mojo::WrapReadOnlySharedMemoryRegion(script.script().Duplicate()));
+ }
+ }
+}
+
+void FrameImpl::MaybeStartCastStreaming(
+ content::NavigationHandle* navigation_handle) {
+ if (!IsCastStreamingEnabled() || !cast_streaming_session_client_)
+ return;
+
+ mojo::AssociatedRemote<mojom::CastStreamingReceiver> cast_streaming_receiver;
+ navigation_handle->GetRenderFrameHost()
+ ->GetRemoteAssociatedInterfaces()
+ ->GetInterface(&cast_streaming_receiver);
+ cast_streaming_session_client_->StartMojoConnection(
+ std::move(cast_streaming_receiver));
+}
+
void FrameImpl::CreateView(fuchsia::ui::views::ViewToken view_token) {
+ 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 FrameImpl::CreateViewWithViewRef(
+ fuchsia::ui::views::ViewToken view_token,
+ fuchsia::ui::views::ViewRefControl control_ref,
+ fuchsia::ui::views::ViewRef view_ref) {
if (IsHeadless()) {
LOG(WARNING) << "CreateView() called on a HEADLESS Context.";
CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
@@ -505,10 +582,13 @@ void FrameImpl::CreateView(fuchsia::ui::views::ViewToken view_token) {
// If a View to this Frame is already active then disconnect it.
DestroyWindowTreeHost();
- InitWindowTreeHost(std::move(view_token));
+ scenic::ViewRefPair view_ref_pair;
+ view_ref_pair.control_ref = std::move(control_ref);
+ view_ref_pair.view_ref = std::move(view_ref);
+ InitWindowTreeHost(std::move(view_token), std::move(view_ref_pair));
fuchsia::accessibility::semantics::SemanticsManagerPtr semantics_manager =
- base::fuchsia::ComponentContextForCurrentProcess()
+ base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::accessibility::semantics::SemanticsManager>();
accessibility_bridge_ = std::make_unique<AccessibilityBridge>(
@@ -619,6 +699,9 @@ void FrameImpl::RemoveBeforeLoadJavaScript(uint64_t id) {
void FrameImpl::PostMessage(std::string origin,
fuchsia::web::WebMessage message,
PostMessageCallback callback) {
+ if (MaybeHandleCastStreamingMessage(&origin, &message, &callback))
+ return;
+
constexpr char kWildcardOrigin[] = "*";
fuchsia::web::Frame_PostMessage_Result result;
@@ -718,7 +801,8 @@ void FrameImpl::EnableHeadlessRendering() {
return;
}
- InitWindowTreeHost(fuchsia::ui::views::ViewToken());
+ scenic::ViewRefPair view_ref_pair = scenic::ViewRefPair::New();
+ InitWindowTreeHost(fuchsia::ui::views::ViewToken(), std::move(view_ref_pair));
gfx::Rect bounds(kHeadlessWindowSize);
if (semantics_manager_for_test_) {
@@ -744,11 +828,12 @@ void FrameImpl::DisableHeadlessRendering() {
DestroyWindowTreeHost();
}
-void FrameImpl::InitWindowTreeHost(fuchsia::ui::views::ViewToken view_token) {
+void FrameImpl::InitWindowTreeHost(fuchsia::ui::views::ViewToken view_token,
+ scenic::ViewRefPair view_ref_pair) {
DCHECK(!window_tree_host_);
window_tree_host_ = std::make_unique<FrameWindowTreeHost>(
- std::move(view_token), web_contents_.get());
+ std::move(view_token), std::move(view_ref_pair), web_contents_.get());
window_tree_host_->InitHost();
root_window()->AddPreTargetHandler(&event_filter_);
@@ -863,7 +948,7 @@ void FrameImpl::SetPermissionState(
void FrameImpl::CloseContents(content::WebContents* source) {
DCHECK_EQ(source, web_contents_.get());
- context_->DestroyFrame(this);
+ CloseAndDestroyFrame(ZX_OK);
}
void FrameImpl::SetBlockMediaLoading(bool blocked) {
@@ -980,30 +1065,13 @@ bool FrameImpl::CheckMediaAccessPermission(
void FrameImpl::ReadyToCommitNavigation(
content::NavigationHandle* navigation_handle) {
- if (before_load_scripts_.empty())
- return;
-
if (!navigation_handle->IsInMainFrame() ||
navigation_handle->IsSameDocument() || navigation_handle->IsErrorPage()) {
return;
}
- mojo::AssociatedRemote<mojom::OnLoadScriptInjector>
- before_load_script_injector;
- navigation_handle->GetRenderFrameHost()
- ->GetRemoteAssociatedInterfaces()
- ->GetInterface(&before_load_script_injector);
-
- // Provision the renderer's ScriptInjector with the scripts scoped to this
- // page's origin.
- before_load_script_injector->ClearOnLoadScripts();
- for (uint64_t script_id : before_load_scripts_order_) {
- const OriginScopedScript& script = before_load_scripts_[script_id];
- if (IsOriginWhitelisted(navigation_handle->GetURL(), script.origins())) {
- before_load_script_injector->AddOnLoadScript(
- mojo::WrapReadOnlySharedMemoryRegion(script.script().Duplicate()));
- }
- }
+ MaybeInjectBeforeLoadScripts(navigation_handle);
+ MaybeStartCastStreaming(navigation_handle);
}
void FrameImpl::DidFinishLoad(content::RenderFrameHost* render_frame_host,
diff --git a/chromium/fuchsia/engine/browser/frame_impl.h b/chromium/fuchsia/engine/browser/frame_impl.h
index 1a852488172..98574ac9b82 100644
--- a/chromium/fuchsia/engine/browser/frame_impl.h
+++ b/chromium/fuchsia/engine/browser/frame_impl.h
@@ -7,6 +7,7 @@
#include <fuchsia/web/cpp/fidl.h>
#include <lib/fidl/cpp/binding_set.h>
+#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <lib/zx/channel.h>
#include <list>
@@ -35,6 +36,7 @@ namespace content {
class FromRenderFrameHost;
} // namespace content
+class CastStreamingSessionClient;
class ContextImpl;
class FrameWindowTreeHost;
class FrameLayoutManager;
@@ -84,6 +86,9 @@ class FrameImpl : public fuchsia::web::Frame,
void set_handle_actions_for_test(bool handle) {
accessibility_bridge_->set_handle_actions_for_test(handle);
}
+ CastStreamingSessionClient* cast_streaming_session_client_for_test() {
+ return cast_streaming_session_client_.get();
+ }
private:
FRIEND_TEST_ALL_PREFIXES(FrameImplTest, DelayedNavigationEventAck);
@@ -130,7 +135,8 @@ class FrameImpl : public fuchsia::web::Frame,
// Initializes WindowTreeHost for the view with the specified |view_token|.
// |view_token| may be uninitialized in headless mode.
- void InitWindowTreeHost(fuchsia::ui::views::ViewToken view_token);
+ void InitWindowTreeHost(fuchsia::ui::views::ViewToken view_token,
+ scenic::ViewRefPair view_ref_pair);
// Destroys the WindowTreeHost along with its view or other associated
// resources.
@@ -139,8 +145,25 @@ class FrameImpl : public fuchsia::web::Frame,
// Destroys |this| and sends the FIDL |error| to the client.
void CloseAndDestroyFrame(zx_status_t error);
+ // Determines whether |message| is a Cast Streaming message and if so, handles
+ // it. Returns whether it handled the message, regardless of whether that was
+ // successful. If true is returned, |callback| has been called. Returns false
+ // immediately if Cast Streaming support is not enabled. Called by
+ // PostMessage().
+ bool MaybeHandleCastStreamingMessage(std::string* origin,
+ fuchsia::web::WebMessage* message,
+ PostMessageCallback* callback);
+
+ void MaybeInjectBeforeLoadScripts(
+ content::NavigationHandle* navigation_handle);
+
+ void MaybeStartCastStreaming(content::NavigationHandle* navigation_handle);
+
// fuchsia::web::Frame implementation.
void CreateView(fuchsia::ui::views::ViewToken view_token) override;
+ void CreateViewWithViewRef(fuchsia::ui::views::ViewToken view_token,
+ fuchsia::ui::views::ViewRefControl control_ref,
+ fuchsia::ui::views::ViewRef view_ref) override;
void GetMediaPlayer(fidl::InterfaceRequest<fuchsia::media::sessions2::Player>
player) override;
void GetNavigationController(
@@ -272,6 +295,7 @@ class FrameImpl : public fuchsia::web::Frame,
gfx::Size render_size_override_;
std::unique_ptr<MediaPlayerImpl> media_player_;
+ std::unique_ptr<CastStreamingSessionClient> cast_streaming_session_client_;
fidl::Binding<fuchsia::web::Frame> binding_;
media_control::MediaBlocker media_blocker_;
diff --git a/chromium/fuchsia/engine/browser/frame_impl_browsertest.cc b/chromium/fuchsia/engine/browser/frame_impl_browsertest.cc
index bccb5200db3..5d19e3757d5 100644
--- a/chromium/fuchsia/engine/browser/frame_impl_browsertest.cc
+++ b/chromium/fuchsia/engine/browser/frame_impl_browsertest.cc
@@ -24,6 +24,7 @@
#include "fuchsia/base/test_navigation_listener.h"
#include "fuchsia/base/url_request_rewrite_test_util.h"
#include "fuchsia/engine/browser/frame_impl.h"
+#include "fuchsia/engine/switches.h"
#include "fuchsia/engine/test/test_data.h"
#include "fuchsia/engine/test/web_engine_browser_test.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -237,9 +238,9 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, ContextDeletedBeforeFrameWithView) {
fuchsia::web::FramePtr frame = CreateFrame();
EXPECT_TRUE(frame);
- auto view_tokens = scenic::NewViewTokenPair();
+ auto view_tokens = scenic::ViewTokenPair::New();
- frame->CreateView(std::move(view_tokens.first));
+ frame->CreateView(std::move(view_tokens.view_token));
base::RunLoop().RunUntilIdle();
base::RunLoop run_loop;
@@ -1191,18 +1192,14 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, PostMessagePassMessagePort) {
"messageport");
fuchsia::web::MessagePortPtr message_port;
- fuchsia::web::WebMessage msg;
{
- fuchsia::web::OutgoingTransferable outgoing;
- outgoing.set_message_port(message_port.NewRequest());
- std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector;
- outgoing_vector.push_back(std::move(outgoing));
- msg.set_outgoing_transfer(std::move(outgoing_vector));
- msg.set_data(cr_fuchsia::MemBufferFromString("hi", "test"));
cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result>
post_result;
frame->PostMessage(
- post_message_url.GetOrigin().spec(), std::move(msg),
+ post_message_url.GetOrigin().spec(),
+ cr_fuchsia::CreateWebMessageWithMessagePortRequest(
+ message_port.NewRequest(),
+ cr_fuchsia::MemBufferFromString("hi", "test")),
cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
base::RunLoop run_loop;
@@ -1216,6 +1213,7 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, PostMessagePassMessagePort) {
}
{
+ fuchsia::web::WebMessage msg;
msg.set_data(cr_fuchsia::MemBufferFromString("ping", "test"));
cr_fuchsia::ResultReceiver<fuchsia::web::MessagePort_PostMessage_Result>
post_result;
@@ -1254,18 +1252,14 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, PostMessageMessagePortDisconnected) {
"messageport");
fuchsia::web::MessagePortPtr message_port;
- fuchsia::web::WebMessage msg;
{
- fuchsia::web::OutgoingTransferable outgoing;
- outgoing.set_message_port(message_port.NewRequest());
- std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector;
- outgoing_vector.push_back(std::move(outgoing));
- msg.set_outgoing_transfer(std::move(outgoing_vector));
- msg.set_data(cr_fuchsia::MemBufferFromString("hi", "test"));
cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result>
post_result;
frame->PostMessage(
- post_message_url.GetOrigin().spec(), std::move(msg),
+ post_message_url.GetOrigin().spec(),
+ cr_fuchsia::CreateWebMessageWithMessagePortRequest(
+ message_port.NewRequest(),
+ cr_fuchsia::MemBufferFromString("hi", "test")),
cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
base::RunLoop run_loop;
@@ -1312,19 +1306,15 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, PostMessageUseContentProvidedPort) {
"messageport");
fuchsia::web::MessagePortPtr incoming_message_port;
- fuchsia::web::WebMessage msg;
{
fuchsia::web::MessagePortPtr message_port;
- fuchsia::web::OutgoingTransferable outgoing;
- outgoing.set_message_port(message_port.NewRequest());
- std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector;
- outgoing_vector.push_back(std::move(outgoing));
- msg.set_outgoing_transfer(std::move(outgoing_vector));
- msg.set_data(cr_fuchsia::MemBufferFromString("hi", "test"));
cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result>
post_result;
frame->PostMessage(
- "*", std::move(msg),
+ "*",
+ cr_fuchsia::CreateWebMessageWithMessagePortRequest(
+ message_port.NewRequest(),
+ cr_fuchsia::MemBufferFromString("hi", "test")),
cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
base::RunLoop run_loop;
@@ -1348,6 +1338,7 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, PostMessageUseContentProvidedPort) {
base::RunLoop run_loop;
cr_fuchsia::ResultReceiver<fuchsia::web::MessagePort_PostMessage_Result>
post_result(run_loop.QuitClosure());
+ fuchsia::web::WebMessage msg;
msg.set_data(cr_fuchsia::MemBufferFromString("ping", "test"));
incoming_message_port->PostMessage(
std::move(msg),
@@ -1360,20 +1351,16 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, PostMessageUseContentProvidedPort) {
// that all the "ack pings" are ready to be consumed.
{
fuchsia::web::MessagePortPtr ack_message_port;
- fuchsia::web::WebMessage msg;
- fuchsia::web::OutgoingTransferable outgoing;
- outgoing.set_message_port(ack_message_port.NewRequest());
- std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector;
- outgoing_vector.push_back(std::move(outgoing));
- msg.set_outgoing_transfer(std::move(outgoing_vector));
- msg.set_data(cr_fuchsia::MemBufferFromString("hi", "test"));
// Quit the runloop only after we've received a WebMessage AND a PostMessage
// result.
cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result>
post_result;
frame->PostMessage(
- "*", std::move(msg),
+ "*",
+ cr_fuchsia::CreateWebMessageWithMessagePortRequest(
+ ack_message_port.NewRequest(),
+ cr_fuchsia::MemBufferFromString("hi", "test")),
cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
base::RunLoop run_loop;
cr_fuchsia::ResultReceiver<fuchsia::web::WebMessage> receiver(
@@ -1422,18 +1409,15 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, PostMessageBadOriginDropped) {
// PostMessage() to invalid origins should be ignored. We pass in a
// MessagePort but nothing should happen to it.
fuchsia::web::MessagePortPtr unused_message_port;
- fuchsia::web::OutgoingTransferable unused_outgoing;
- unused_outgoing.set_message_port(unused_message_port.NewRequest());
- std::vector<fuchsia::web::OutgoingTransferable> unused_outgoing_vector;
- unused_outgoing_vector.push_back(std::move(unused_outgoing));
- msg.set_outgoing_transfer(std::move(unused_outgoing_vector));
- msg.set_data(cr_fuchsia::MemBufferFromString("bad origin, bad!", "test"));
-
cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result>
unused_post_result;
- frame->PostMessage("https://example.com", std::move(msg),
- cr_fuchsia::CallbackToFitFunction(
- unused_post_result.GetReceiveCallback()));
+ frame->PostMessage(
+ "https://example.com",
+ cr_fuchsia::CreateWebMessageWithMessagePortRequest(
+ unused_message_port.NewRequest(),
+ cr_fuchsia::MemBufferFromString("bad origin, bad!", "test")),
+ cr_fuchsia::CallbackToFitFunction(
+ unused_post_result.GetReceiveCallback()));
cr_fuchsia::ResultReceiver<fuchsia::web::WebMessage> unused_message_read;
bad_origin_incoming_message_port->ReceiveMessage(
cr_fuchsia::CallbackToFitFunction(
@@ -1446,17 +1430,13 @@ IN_PROC_BROWSER_TEST_F(FrameImplTest, PostMessageBadOriginDropped) {
// discarded.
fuchsia::web::MessagePortPtr incoming_message_port;
fuchsia::web::MessagePortPtr message_port;
- fuchsia::web::OutgoingTransferable outgoing;
- outgoing.set_message_port(message_port.NewRequest());
- std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector;
- outgoing_vector.push_back(std::move(outgoing));
- msg.set_outgoing_transfer(std::move(outgoing_vector));
- msg.set_data(cr_fuchsia::MemBufferFromString("good origin", "test"));
-
cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result>
post_result;
frame->PostMessage(
- "*", std::move(msg),
+ "*",
+ cr_fuchsia::CreateWebMessageWithMessagePortRequest(
+ message_port.NewRequest(),
+ cr_fuchsia::MemBufferFromString("good origin", "test")),
cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
base::RunLoop run_loop;
cr_fuchsia::ResultReceiver<fuchsia::web::WebMessage> receiver(
@@ -1696,6 +1676,11 @@ class RequestMonitoringFrameImplBrowserTest : public FrameImplTest {
embedded_test_server()->StartAndReturnHandle());
}
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ // Needed for UrlRequestRewriteAddHeaders.
+ command_line->AppendSwitchNative(switches::kCorsExemptHeaders, "Test");
+ }
+
std::map<GURL, net::test_server::HttpRequest> accumulated_requests_;
private:
diff --git a/chromium/fuchsia/engine/browser/frame_window_tree_host.cc b/chromium/fuchsia/engine/browser/frame_window_tree_host.cc
index 5fc20eb54cd..4ad2732c543 100644
--- a/chromium/fuchsia/engine/browser/frame_window_tree_host.cc
+++ b/chromium/fuchsia/engine/browser/frame_window_tree_host.cc
@@ -51,13 +51,14 @@ class FrameWindowTreeHost::WindowParentingClientImpl
FrameWindowTreeHost::FrameWindowTreeHost(
fuchsia::ui::views::ViewToken view_token,
+ scenic::ViewRefPair view_ref_pair,
content::WebContents* web_contents)
: web_contents_(web_contents) {
CreateCompositor();
ui::PlatformWindowInitProperties properties;
properties.view_token = std::move(view_token);
- properties.view_ref_pair = scenic::ViewRefPair::New();
+ properties.view_ref_pair = std::move(view_ref_pair);
view_ref_ = DupViewRef(properties.view_ref_pair.view_ref);
CreateAndSetPlatformWindow(std::move(properties));
diff --git a/chromium/fuchsia/engine/browser/frame_window_tree_host.h b/chromium/fuchsia/engine/browser/frame_window_tree_host.h
index 17fe15f5c5a..0e517bcf5d1 100644
--- a/chromium/fuchsia/engine/browser/frame_window_tree_host.h
+++ b/chromium/fuchsia/engine/browser/frame_window_tree_host.h
@@ -19,6 +19,7 @@ class FrameWindowTreeHost : public aura::WindowTreeHostPlatform {
public:
// |web_contents| must to outlive |FrameWindowTreeHost|.
FrameWindowTreeHost(fuchsia::ui::views::ViewToken view_token,
+ scenic::ViewRefPair view_ref_pair,
content::WebContents* web_contents);
~FrameWindowTreeHost() final;
diff --git a/chromium/fuchsia/engine/browser/media_resource_provider_service.cc b/chromium/fuchsia/engine/browser/media_resource_provider_service.cc
index c3e36e13202..154a96304cc 100644
--- a/chromium/fuchsia/engine/browser/media_resource_provider_service.cc
+++ b/chromium/fuchsia/engine/browser/media_resource_provider_service.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 "content/public/browser/browser_context.h"
#include "content/public/browser/frame_service_base.h"
#include "content/public/browser/provision_fetcher_factory.h"
@@ -79,7 +79,7 @@ void MediaResourceProviderImpl::CreateCdm(
void MediaResourceProviderImpl::CreateAudioConsumer(
fidl::InterfaceRequest<fuchsia::media::AudioConsumer> request) {
- auto factory = base::fuchsia::ComponentContextForCurrentProcess()
+ auto factory = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::media::SessionAudioConsumerFactory>();
factory->CreateAudioConsumer(
@@ -100,7 +100,7 @@ void MediaResourceProviderImpl::CreateAudioCapturer(
return;
}
- auto factory = base::fuchsia::ComponentContextForCurrentProcess()
+ auto factory = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::media::Audio>();
factory->CreateAudioCapturer(std::move(request), /*loopback=*/false);
@@ -114,7 +114,7 @@ class WidevineHandler : public media::FuchsiaCdmManager::KeySystemHandler {
void CreateCdm(
fidl::InterfaceRequest<fuchsia::media::drm::ContentDecryptionModule>
request) override {
- auto widevine = base::fuchsia::ComponentContextForCurrentProcess()
+ auto widevine = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::media::drm::Widevine>();
widevine->CreateContentDecryptionModule(std::move(request));
@@ -123,7 +123,7 @@ class WidevineHandler : public media::FuchsiaCdmManager::KeySystemHandler {
fuchsia::media::drm::ProvisionerPtr CreateProvisioner() override {
fuchsia::media::drm::ProvisionerPtr provisioner;
- auto widevine = base::fuchsia::ComponentContextForCurrentProcess()
+ auto widevine = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::media::drm::Widevine>();
widevine->CreateProvisioner(provisioner.NewRequest());
@@ -140,7 +140,7 @@ class PlayreadyHandler : public media::FuchsiaCdmManager::KeySystemHandler {
void CreateCdm(
fidl::InterfaceRequest<fuchsia::media::drm::ContentDecryptionModule>
request) override {
- auto playready = base::fuchsia::ComponentContextForCurrentProcess()
+ auto playready = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::media::drm::PlayReady>();
playready->CreateContentDecryptionModule(std::move(request));
diff --git a/chromium/fuchsia/engine/browser/navigation_controller_impl.cc b/chromium/fuchsia/engine/browser/navigation_controller_impl.cc
index 4c95d83979f..79879065f9d 100644
--- a/chromium/fuchsia/engine/browser/navigation_controller_impl.cc
+++ b/chromium/fuchsia/engine/browser/navigation_controller_impl.cc
@@ -15,36 +15,6 @@
#include "net/http/http_util.h"
#include "ui/base/page_transition_types.h"
-namespace {
-
-void UpdateNavigationStateFromNavigationEntry(
- content::NavigationEntry* entry,
- content::WebContents* web_contents,
- fuchsia::web::NavigationState* navigation_state) {
- DCHECK(entry);
- DCHECK(web_contents);
- DCHECK(navigation_state);
-
- navigation_state->set_title(base::UTF16ToUTF8(entry->GetTitleForDisplay()));
- navigation_state->set_url(entry->GetURL().spec());
-
- switch (entry->GetPageType()) {
- case content::PageType::PAGE_TYPE_NORMAL:
- case content::PageType::PAGE_TYPE_INTERSTITIAL:
- navigation_state->set_page_type(fuchsia::web::PageType::NORMAL);
- break;
- case content::PageType::PAGE_TYPE_ERROR:
- navigation_state->set_page_type(fuchsia::web::PageType::ERROR);
- break;
- }
-
- navigation_state->set_can_go_back(web_contents->GetController().CanGoBack());
- navigation_state->set_can_go_forward(
- web_contents->GetController().CanGoForward());
-}
-
-} // namespace
-
NavigationControllerImpl::NavigationControllerImpl(
content::WebContents* web_contents)
: web_contents_(web_contents), weak_factory_(this) {
@@ -88,19 +58,48 @@ void NavigationControllerImpl::SetEventListener(
}
}
-void NavigationControllerImpl::OnNavigationEntryChanged() {
- fuchsia::web::NavigationState new_state;
- new_state.set_is_main_document_loaded(is_main_document_loaded_);
- UpdateNavigationStateFromNavigationEntry(
- web_contents_->GetController().GetVisibleEntry(), web_contents_,
- &new_state);
- if (new_state.page_type() != fuchsia::web::PageType::ERROR &&
- uncommitted_load_error_) {
+fuchsia::web::NavigationState
+NavigationControllerImpl::GetVisibleNavigationState() const {
+ content::NavigationEntry* const entry =
+ web_contents_->GetController().GetVisibleEntry();
+ if (!entry)
+ return fuchsia::web::NavigationState();
+
+ fuchsia::web::NavigationState state;
+
+ // Populate some fields directly from the NavigationEntry.
+ state.set_title(base::UTF16ToUTF8(entry->GetTitleForDisplay()));
+ state.set_url(entry->GetURL().spec());
+
+ if (web_contents_->IsCrashed()) {
+ // TODO(https:://crbug.com/1092506): Add an explicit crashed indicator to
+ // NavigationState, separate from PageType::ERROR.
+ state.set_page_type(fuchsia::web::PageType::ERROR);
+ } else if (uncommitted_load_error_) {
// If there was a loading error which prevented the navigation entry from
- // being committed, then reflect the error in |new_state|.
- new_state.set_page_type(fuchsia::web::PageType::ERROR);
+ // being committed, then report PageType::ERROR.
+ state.set_page_type(fuchsia::web::PageType::ERROR);
+ } else {
+ switch (entry->GetPageType()) {
+ case content::PageType::PAGE_TYPE_NORMAL:
+ case content::PageType::PAGE_TYPE_INTERSTITIAL:
+ state.set_page_type(fuchsia::web::PageType::NORMAL);
+ break;
+ case content::PageType::PAGE_TYPE_ERROR:
+ state.set_page_type(fuchsia::web::PageType::ERROR);
+ break;
+ }
}
+ state.set_is_main_document_loaded(is_main_document_loaded_);
+ state.set_can_go_back(web_contents_->GetController().CanGoBack());
+ state.set_can_go_forward(web_contents_->GetController().CanGoForward());
+
+ return state;
+}
+
+void NavigationControllerImpl::OnNavigationEntryChanged() {
+ fuchsia::web::NavigationState new_state = GetVisibleNavigationState();
DiffNavigationEntries(previous_navigation_state_, new_state,
&pending_navigation_event_);
previous_navigation_state_ = std::move(new_state);
@@ -209,17 +208,7 @@ void NavigationControllerImpl::Reload(fuchsia::web::ReloadType type) {
void NavigationControllerImpl::GetVisibleEntry(
fuchsia::web::NavigationController::GetVisibleEntryCallback callback) {
- content::NavigationEntry* entry =
- web_contents_->GetController().GetVisibleEntry();
- if (!entry) {
- callback({});
- return;
- }
-
- fuchsia::web::NavigationState state;
- state.set_is_main_document_loaded(is_main_document_loaded_);
- UpdateNavigationStateFromNavigationEntry(entry, web_contents_, &state);
- callback(std::move(state));
+ callback(GetVisibleNavigationState());
}
void NavigationControllerImpl::TitleWasSet(content::NavigationEntry* entry) {
@@ -242,6 +231,14 @@ void NavigationControllerImpl::DidFinishLoad(
OnNavigationEntryChanged();
}
+void NavigationControllerImpl::RenderProcessGone(
+ base::TerminationStatus status) {
+ // If the current RenderProcess terminates then trigger a NavigationState
+ // change to let the caller know that something is wrong.
+ LOG(WARNING) << "RenderProcess gone, TerminationStatus=" << status;
+ OnNavigationEntryChanged();
+}
+
void NavigationControllerImpl::DidStartNavigation(
content::NavigationHandle* navigation_handle) {
uncommitted_load_error_ = false;
diff --git a/chromium/fuchsia/engine/browser/navigation_controller_impl.h b/chromium/fuchsia/engine/browser/navigation_controller_impl.h
index 1d48ad27976..9a34c7f3d0a 100644
--- a/chromium/fuchsia/engine/browser/navigation_controller_impl.h
+++ b/chromium/fuchsia/engine/browser/navigation_controller_impl.h
@@ -33,6 +33,11 @@ class NavigationControllerImpl : public fuchsia::web::NavigationController,
fidl::InterfaceHandle<fuchsia::web::NavigationEventListener> listener);
private:
+ // Returns a NavigationState reflecting the current state of |web_contents_|'s
+ // visible navigation entry, taking into account |is_main_document_loaded_|
+ // and |uncommitted_load_error_| states.
+ fuchsia::web::NavigationState GetVisibleNavigationState() const;
+
// Processes the most recent changes to the browser's navigation state and
// triggers the publishing of change events.
void OnNavigationEntryChanged();
@@ -56,6 +61,7 @@ class NavigationControllerImpl : public fuchsia::web::NavigationController,
void DocumentAvailableInMainFrame() final;
void DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) final;
+ void RenderProcessGone(base::TerminationStatus status) final;
void DidStartNavigation(content::NavigationHandle* navigation_handle) final;
void DidFinishNavigation(content::NavigationHandle* navigation_handle) final;
diff --git a/chromium/fuchsia/engine/browser/web_engine_browser_context.cc b/chromium/fuchsia/engine/browser/web_engine_browser_context.cc
index de9ce2c7b40..03a6e9fa3a7 100644
--- a/chromium/fuchsia/engine/browser/web_engine_browser_context.cc
+++ b/chromium/fuchsia/engine/browser/web_engine_browser_context.cc
@@ -12,7 +12,6 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
-#include "base/task/post_task.h"
#include "components/keyed_service/core/simple_key_map.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -67,8 +66,8 @@ WebEngineBrowserContext::~WebEngineBrowserContext() {
NotifyWillBeDestroyed(this);
if (resource_context_) {
- base::DeleteSoon(FROM_HERE, {content::BrowserThread::IO},
- std::move(resource_context_));
+ content::GetIOThreadTaskRunner({})->DeleteSoon(
+ FROM_HERE, std::move(resource_context_));
}
ShutdownStoragePartitions();
diff --git a/chromium/fuchsia/engine/browser/web_engine_content_browser_client.cc b/chromium/fuchsia/engine/browser/web_engine_content_browser_client.cc
index 6d77b2eb8bf..0fb644e3883 100644
--- a/chromium/fuchsia/engine/browser/web_engine_content_browser_client.cc
+++ b/chromium/fuchsia/engine/browser/web_engine_content_browser_client.cc
@@ -11,9 +11,9 @@
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "components/version_info/version_info.h"
-#include "content/public/browser/cors_exempt_headers.h"
#include "content/public/browser/devtools_manager_delegate.h"
#include "content/public/browser/network_service_instance.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/user_agent.h"
#include "content/public/common/web_preferences.h"
#include "fuchsia/base/fuchsia_dir_scheme.h"
@@ -153,13 +153,16 @@ void WebEngineContentBrowserClient::
void WebEngineContentBrowserClient::AppendExtraCommandLineSwitches(
base::CommandLine* command_line,
int child_process_id) {
+ // TODO(https://crbug.com/1083520): Pass based on process type.
constexpr char const* kSwitchesToCopy[] = {
switches::kContentDirectories,
switches::kCorsExemptHeaders,
switches::kDisableSoftwareVideoDecoders,
+ switches::kEnableCastStreamingReceiver,
switches::kEnableProtectedVideoBuffers,
switches::kEnableWidevine,
switches::kForceProtectedVideoOutputBuffers,
+ switches::kMaxDecodedImageSizeMb,
switches::kPlayreadyKeySystem,
};
@@ -206,8 +209,4 @@ void WebEngineContentBrowserClient::ConfigureNetworkContextParams(
// starting with the headers passed in via
// |CreateContextParams.cors_exempt_headers|.
network_context_params->cors_exempt_header_list = cors_exempt_headers_;
-
- // Exempt the minimal headers needed for CORS preflight checks (Purpose,
- // X-Requested-With).
- content::UpdateCorsExemptHeader(network_context_params);
}
diff --git a/chromium/fuchsia/engine/browser/web_engine_net_log_observer.cc b/chromium/fuchsia/engine/browser/web_engine_net_log_observer.cc
index 66f454574e2..c24b7215ab9 100644
--- a/chromium/fuchsia/engine/browser/web_engine_net_log_observer.cc
+++ b/chromium/fuchsia/engine/browser/web_engine_net_log_observer.cc
@@ -20,7 +20,8 @@ namespace {
std::unique_ptr<base::DictionaryValue> GetWebEngineConstants() {
std::unique_ptr<base::DictionaryValue> constants_dict =
- net::GetNetConstants();
+ base::DictionaryValue::From(
+ base::Value::ToUniquePtrValue(net::GetNetConstants()));
base::DictionaryValue dict;
dict.SetKey("name", base::Value("WebEngine"));
diff --git a/chromium/fuchsia/engine/cast_streaming_session.mojom b/chromium/fuchsia/engine/cast_streaming_session.mojom
new file mode 100644
index 00000000000..33af21c3e95
--- /dev/null
+++ b/chromium/fuchsia/engine/cast_streaming_session.mojom
@@ -0,0 +1,59 @@
+// 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.
+
+module mojom;
+
+import "media/mojo/mojom/media_types.mojom";
+
+// Renderer-implemented interface that is used to receive metadata for buffers.
+interface CastStreamingBufferReceiver {
+ // Provide metadata for a buffer to the Cast Streaming Receiver in the
+ // renderer process. The buffer data itself is on the associated |data_pipe|,
+ // from AudioStreamInfo or VideoStreamInfo.
+ // This is called for every new buffer pushed in the associated |data_pipe|.
+ ProvideBuffer(media.mojom.DecoderBuffer buffer);
+};
+
+// Information about a Cast Streaming audio stream.
+struct AudioStreamInfo {
+ // Audio decoder configuration.
+ media.mojom.AudioDecoderConfig decoder_config;
+
+ // Audio buffer metadata receiver.
+ pending_receiver<CastStreamingBufferReceiver> buffer_receiver;
+
+ // Mojo data pipe over which audio buffer data is sent.
+ handle<data_pipe_consumer> data_pipe;
+};
+
+// Information about a Cast Streaming video stream.
+struct VideoStreamInfo {
+ // Video decoder configuration.
+ media.mojom.VideoDecoderConfig decoder_config;
+
+ // Video buffer metadata receiver.
+ pending_receiver<CastStreamingBufferReceiver> buffer_receiver;
+
+ // Mojo data pipe over which video buffer data is sent.
+ handle<data_pipe_consumer> data_pipe;
+};
+
+// Implemented by the renderer, used to start the Cast Streaming Session.
+// Closure of the Mojo channel will trigger the end of the Cast Streaming
+// Session.
+interface CastStreamingReceiver {
+ // Used for synchronization between the browser and the renderer. The browser
+ // should invoke this after binding the interface, and wait for the reply
+ // callback to know when the renderer is ready to receive and render frames.
+ EnableReceiver() => ();
+
+ // Called when the streams have been successfully initialized. At least one of
+ // |audio_stream_info| or |video_stream_info| must be set. This will only be
+ // called once per the lifetime of CastStreamingReceiver. After this call,
+ // CastStreamingBufferReceiver.ProvideBuffer() will be called on every new
+ // frame.
+ OnStreamsInitialized(
+ AudioStreamInfo? audio_stream_info,
+ VideoStreamInfo? video_stream_info);
+};
diff --git a/chromium/fuchsia/engine/common/cast_streaming.cc b/chromium/fuchsia/engine/common/cast_streaming.cc
new file mode 100644
index 00000000000..a224697fce3
--- /dev/null
+++ b/chromium/fuchsia/engine/common/cast_streaming.cc
@@ -0,0 +1,24 @@
+// 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/engine/common/cast_streaming.h"
+
+#include "base/command_line.h"
+#include "fuchsia/engine/switches.h"
+#include "url/gurl.h"
+
+namespace {
+constexpr char kCastStreamingReceiverUrl[] = "data:cast_streaming_receiver";
+} // namespace
+
+bool IsCastStreamingEnabled() {
+ static bool is_cast_streaming_enabled =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableCastStreamingReceiver);
+ return is_cast_streaming_enabled;
+}
+
+bool IsCastStreamingMediaSourceUrl(const GURL& url) {
+ return url == kCastStreamingReceiverUrl;
+}
diff --git a/chromium/fuchsia/engine/common/cast_streaming.h b/chromium/fuchsia/engine/common/cast_streaming.h
new file mode 100644
index 00000000000..660c4b538ea
--- /dev/null
+++ b/chromium/fuchsia/engine/common/cast_streaming.h
@@ -0,0 +1,16 @@
+// 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_ENGINE_COMMON_CAST_STREAMING_H_
+#define FUCHSIA_ENGINE_COMMON_CAST_STREAMING_H_
+
+class GURL;
+
+// Returns true if Cast Streaming is enabled for this process.
+bool IsCastStreamingEnabled();
+
+// Returns true if |url| is the Cast Streaming media source URL.
+bool IsCastStreamingMediaSourceUrl(const GURL& url);
+
+#endif // FUCHSIA_ENGINE_COMMON_CAST_STREAMING_H_
diff --git a/chromium/fuchsia/engine/common/web_engine_content_client.cc b/chromium/fuchsia/engine/common/web_engine_content_client.cc
index 24c9a741950..30d007dfe4c 100644
--- a/chromium/fuchsia/engine/common/web_engine_content_client.cc
+++ b/chromium/fuchsia/engine/common/web_engine_content_client.cc
@@ -5,6 +5,7 @@
#include "fuchsia/engine/common/web_engine_content_client.h"
#include "base/command_line.h"
+#include "base/notreached.h"
#include "fuchsia/base/fuchsia_dir_scheme.h"
#include "fuchsia/engine/switches.h"
#include "ui/base/l10n/l10n_util.h"
diff --git a/chromium/fuchsia/engine/context_provider.cmx b/chromium/fuchsia/engine/context_provider.cmx
index 4018804f3da..a36b72bc4f8 100644
--- a/chromium/fuchsia/engine/context_provider.cmx
+++ b/chromium/fuchsia/engine/context_provider.cmx
@@ -8,6 +8,7 @@
],
"services": [
"fuchsia.feedback.ComponentDataRegister",
+ "fuchsia.feedback.CrashReportingProductRegister",
"fuchsia.logger.LogSink",
"fuchsia.process.Launcher"
]
diff --git a/chromium/fuchsia/engine/context_provider_impl.cc b/chromium/fuchsia/engine/context_provider_impl.cc
index ce95251599c..e6054330e3c 100644
--- a/chromium/fuchsia/engine/context_provider_impl.cc
+++ b/chromium/fuchsia/engine/context_provider_impl.cc
@@ -54,6 +54,7 @@
#include "net/http/http_util.h"
#include "services/network/public/cpp/features.h"
#include "services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h"
+#include "third_party/blink/public/common/switches.h"
#include "third_party/widevine/cdm/widevine_cdm_common.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
@@ -61,6 +62,13 @@
namespace {
+// Use a constexpr instead of the existing base::Feature, because of the
+// additional dependencies required.
+constexpr char kMixedContentAutoupgradeFeatureName[] =
+ "AutoupgradeMixedContent";
+constexpr char kDisableMixedContentAutoupgradeOrigin[] =
+ "disable-mixed-content-autoupgrade";
+
// Returns the underlying channel if |directory| is a client endpoint for a
// |fuchsia::io::Directory| protocol. Otherwise, returns an empty channel.
zx::channel ValidateDirectoryAndTakeChannel(
@@ -154,25 +162,30 @@ bool MaybeAddCommandLineArgsFromConfig(const base::Value& config,
return true;
static const base::StringPiece kAllowedArgs[] = {
+ blink::switches::kGpuRasterizationMSAASampleCount,
+ blink::switches::kMinHeightForGpuRasterTile,
cc::switches::kEnableGpuBenchmarking,
- switches::kAcceleratedCanvas2dMSAASampleCount,
switches::kDisableFeatures,
switches::kDisableGpuWatchdog,
+ // TODO(crbug.com/1082821): Remove this switch from the allow-list.
+ switches::kEnableCastStreamingReceiver,
switches::kEnableFeatures,
switches::kEnableLowEndDeviceMode,
switches::kForceGpuMemAvailableMb,
switches::kForceGpuMemDiscardableLimitMb,
switches::kForceMaxTextureSize,
- switches::kGpuRasterizationMSAASampleCount,
- switches::kMinHeightForGpuRasterTile,
+ switches::kMaxDecodedImageSizeMb,
switches::kRendererProcessLimit,
+ switches::kWebglAntialiasingMode,
+ switches::kWebglMSAASampleCount,
};
for (const auto& arg : args->DictItems()) {
if (!base::Contains(kAllowedArgs, arg.first)) {
- LOG(ERROR) << "Unknown command-line arg: " << arg.first;
- // TODO(https://crbug.com/1032439): Return false here once we are done
- // experimenting with memory-related command-line options.
+ // TODO(https://crbug.com/1032439): Increase severity and return false
+ // once we have a mechanism for soft transitions of supported arguments.
+ LOG(WARNING) << "Unknown command-line arg: '" << arg.first
+ << "'. Config file and WebEngine version may not match.";
continue;
}
@@ -191,7 +204,7 @@ bool MaybeAddCommandLineArgsFromConfig(const base::Value& config,
// which
// we don't yet support.
if (arg.first == switches::kEnableLowEndDeviceMode)
- command_line->AppendSwitch(switches::kDisableRGBA4444Textures);
+ command_line->AppendSwitch(blink::switches::kDisableRGBA4444Textures);
}
return true;
@@ -211,12 +224,6 @@ bool IsFuchsiaCdmSupported() {
#endif
}
-// Use the most significant bit to enable cast streaming receiver features.
-// TODO(crbug.com/1078919): Remove this when we have a better way of enabling
-// this feature.
-constexpr auto kCastStreamingFeatureFlag =
- static_cast<fuchsia::web::ContextFeatureFlags>(1ULL << 63);
-
} // namespace
const uint32_t ContextProviderImpl::kContextRequestHandleId =
@@ -405,18 +412,8 @@ void ContextProviderImpl::Create(
// SkiaRenderer requires out-of-process rasterization be enabled.
launch_command.AppendSwitch(switches::kEnableOopRasterization);
- if (!enable_protected_graphics) {
- launch_command.AppendSwitchASCII(switches::kUseGL,
- gl::kGLImplementationANGLEName);
- } else {
- DLOG(WARNING) << "ANGLE is not compatible with "
- << switches::kEnforceVulkanProtectedMemory
- << ", disabling GL";
- // TODO(crbug.com/1059010): Fix this; probably don't protect canvas
- // resources.
- launch_command.AppendSwitchASCII(switches::kUseGL,
- gl::kGLImplementationStubName);
- }
+ launch_command.AppendSwitchASCII(switches::kUseGL,
+ gl::kGLImplementationANGLEName);
} else {
VLOG(1) << "Disabling GPU acceleration.";
// Disable use of Vulkan GPU, and use of the software-GL rasterizer. The
@@ -460,11 +457,6 @@ void ContextProviderImpl::Create(
launch_command.AppendSwitch(switches::kDisableSoftwareVideoDecoders);
}
- const bool enable_cast_streaming_receiver =
- (features & kCastStreamingFeatureFlag) == kCastStreamingFeatureFlag;
- if (enable_cast_streaming_receiver)
- launch_command.AppendSwitch(switches::kEnableCastStreamingReceiver);
-
// Validate embedder-supplied product, and optional version, and pass it to
// the Context to include in the UserAgent.
if (params.has_user_agent_product()) {
@@ -502,10 +494,13 @@ void ContextProviderImpl::Create(
if (params.has_unsafely_treat_insecure_origins_as_secure()) {
const std::vector<std::string>& insecure_origins =
params.unsafely_treat_insecure_origins_as_secure();
- if (std::find(insecure_origins.begin(), insecure_origins.end(),
- switches::kAllowRunningInsecureContent) !=
- insecure_origins.end()) {
- launch_command.AppendSwitch(switches::kAllowRunningInsecureContent);
+ for (auto origin : insecure_origins) {
+ if (origin == switches::kAllowRunningInsecureContent)
+ launch_command.AppendSwitch(switches::kAllowRunningInsecureContent);
+ if (origin == kDisableMixedContentAutoupgradeOrigin) {
+ AppendFeature(switches::kDisableFeatures,
+ kMixedContentAutoupgradeFeatureName, &launch_command);
+ }
}
// TODO(crbug.com/1023510): Pass the rest of the list to the Context
// process.
@@ -522,10 +517,19 @@ void ContextProviderImpl::Create(
base::JoinString(cors_exempt_headers, ","));
}
- if (launch_for_test_)
- launch_for_test_.Run(launch_command, launch_options);
- else
- base::LaunchProcess(launch_command, launch_options);
+ base::Process context_process;
+ if (launch_for_test_) {
+ context_process = launch_for_test_.Run(launch_command, launch_options);
+ } else {
+ context_process = base::LaunchProcess(launch_command, launch_options);
+ }
+
+ if (context_process.IsValid()) {
+ // Set |context_process| termination to teardown its job and sub-processes.
+ zx_status_t result = zx_job_set_critical(launch_options.job_handle, 0,
+ context_process.Handle());
+ ZX_CHECK(ZX_OK == result, result) << "zx_job_set_critical";
+ }
// |context_request| and any DevTools channels were transferred (not copied)
// to the Context process.
diff --git a/chromium/fuchsia/engine/context_provider_impl_unittest.cc b/chromium/fuchsia/engine/context_provider_impl_unittest.cc
index e6aae9929c8..22eeaa655c3 100644
--- a/chromium/fuchsia/engine/context_provider_impl_unittest.cc
+++ b/chromium/fuchsia/engine/context_provider_impl_unittest.cc
@@ -506,35 +506,3 @@ TEST(ContextProviderImplConfigTest, WithConfigWithWronglyTypedCommandLineArgs) {
loop.Run();
}
-
-// Tests setting the custom Cast Streaming Receiver feature flag properly adds
-// the Cast Streaming Receiver switch.
-TEST(ContextProviderImplReceiverTest, CastStreamingReceiverFeatureFlag) {
- const base::test::SingleThreadTaskEnvironment task_environment_{
- base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
-
- constexpr auto kCastStreamingFeatureFlag =
- static_cast<fuchsia::web::ContextFeatureFlags>(1ULL << 63);
-
- base::RunLoop loop;
- ContextProviderImpl context_provider;
- context_provider.SetLaunchCallbackForTest(
- base::BindLambdaForTesting([&](const base::CommandLine& command,
- const base::LaunchOptions& options) {
- EXPECT_TRUE(command.HasSwitch(switches::kEnableCastStreamingReceiver));
- loop.Quit();
- return base::Process();
- }));
-
- fuchsia::web::ContextPtr context;
- context.set_error_handler([&loop](zx_status_t status) {
- ADD_FAILURE();
- loop.Quit();
- });
-
- fuchsia::web::CreateContextParams params = BuildCreateContextParams();
- params.set_features(kCastStreamingFeatureFlag);
- context_provider.Create(std::move(params), context.NewRequest());
-
- loop.Run();
-}
diff --git a/chromium/fuchsia/engine/context_provider_main.cc b/chromium/fuchsia/engine/context_provider_main.cc
index 50195913faf..87cf253076e 100644
--- a/chromium/fuchsia/engine/context_provider_main.cc
+++ b/chromium/fuchsia/engine/context_provider_main.cc
@@ -9,19 +9,27 @@
#include <lib/sys/cpp/outgoing_directory.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/logging.h"
#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_executor.h"
#include "components/version_info/version_info.h"
+#include "fuchsia/base/feedback_registration.h"
#include "fuchsia/base/init_logging.h"
+#include "fuchsia/base/inspect.h"
#include "fuchsia/base/lifecycle_impl.h"
#include "fuchsia/engine/context_provider_impl.h"
namespace {
+constexpr char kFeedbackAnnotationsNamespace[] = "web-engine";
+constexpr char kCrashProductName[] = "FuchsiaWebEngine";
+// TODO(https://fxbug.dev/51490): Use a programmatic mechanism to obtain this.
+constexpr char kComponentUrl[] =
+ "fuchsia-pkg://fuchsia.com/web_engine#meta/context_provider.cmx";
+
std::string GetVersionString() {
std::string version_string = version_info::GetVersionNumber();
#if !defined(OFFICIAL_BUILD)
@@ -30,14 +38,16 @@ std::string GetVersionString() {
return version_string;
}
+// TODO(ddorwin): Move to feedback_registration.h.
// TODO(https://crbug.com/1010222): Add annotations at Context startup, once
// Contexts are moved out to run in their own components.
void RegisterFeedbackAnnotations() {
fuchsia::feedback::ComponentData component_data;
- component_data.set_namespace_("web-engine");
+ component_data.set_namespace_(kFeedbackAnnotationsNamespace);
+ // TODO(https://crbug.com/1077428): Add release channel to the annotations.
component_data.mutable_annotations()->push_back(
{"version", version_info::GetVersionNumber()});
- base::fuchsia::ComponentContextForCurrentProcess()
+ base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::feedback::ComponentDataRegister>()
->Upsert(std::move(component_data), []() {});
@@ -48,6 +58,8 @@ void RegisterFeedbackAnnotations() {
int ContextProviderMain() {
base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI);
+ cr_fuchsia::RegisterCrashReportingFields(kComponentUrl, kCrashProductName);
+
if (!cr_fuchsia::InitLoggingFromCommandLine(
*base::CommandLine::ForCurrentProcess())) {
return 1;
@@ -62,12 +74,15 @@ int ContextProviderMain() {
// Publish the ContextProvider and Debug services.
sys::OutgoingDirectory* const directory =
- base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get();
+ base::ComponentContextForProcess()->outgoing().get();
base::fuchsia::ScopedServiceBinding<fuchsia::web::ContextProvider> binding(
directory, &context_provider);
base::fuchsia::ScopedServiceBinding<fuchsia::web::Debug> debug_binding(
directory->debug_dir(), &context_provider);
+ // Publish version information for this component to Inspect.
+ cr_fuchsia::PublishVersionInfoToInspect(base::ComponentInspectorForProcess());
+
// Publish the Lifecycle service, used by the framework to request that the
// service terminate.
base::RunLoop run_loop;
diff --git a/chromium/fuchsia/engine/on_load_script_injector.mojom b/chromium/fuchsia/engine/on_load_script_injector.mojom
index a641eff9392..1cac32b2c3d 100644
--- a/chromium/fuchsia/engine/on_load_script_injector.mojom
+++ b/chromium/fuchsia/engine/on_load_script_injector.mojom
@@ -8,6 +8,7 @@ module mojom;
// injection tasks the frame. Does not enforce script injection policies,
// which must be implemented at a higher level.
interface OnLoadScriptInjector {
+ // TODO(crbug.com/1060846): Stop using handle<shared_buffer>.
AddOnLoadScript(handle<shared_buffer> script);
ClearOnLoadScripts();
diff --git a/chromium/fuchsia/engine/renderer/cast_streaming_demuxer.cc b/chromium/fuchsia/engine/renderer/cast_streaming_demuxer.cc
new file mode 100644
index 00000000000..92937f33b35
--- /dev/null
+++ b/chromium/fuchsia/engine/renderer/cast_streaming_demuxer.cc
@@ -0,0 +1,352 @@
+// 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/engine/renderer/cast_streaming_demuxer.h"
+
+#include "base/bind.h"
+#include "base/sequence_checker.h"
+#include "base/single_thread_task_runner.h"
+#include "fuchsia/engine/renderer/cast_streaming_receiver.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/decoder_buffer.h"
+#include "media/base/timestamp_constants.h"
+#include "media/base/video_decoder_config.h"
+#include "media/mojo/common/mojo_decoder_buffer_converter.h"
+
+namespace {
+
+// media::DemuxerStream shared audio/video implementation for Cast Streaming.
+// Receives buffer metadata over a Mojo service and reads the buffers over a
+// Mojo data pipe from the browser process.
+class CastStreamingDemuxerStream : public media::DemuxerStream,
+ public mojom::CastStreamingBufferReceiver {
+ public:
+ CastStreamingDemuxerStream(
+ mojo::PendingReceiver<mojom::CastStreamingBufferReceiver>
+ pending_receiver,
+ mojo::ScopedDataPipeConsumerHandle consumer)
+ : receiver_(this, std::move(pending_receiver)),
+ decoder_buffer_reader_(std::move(consumer)) {
+ DVLOG(1) << __func__;
+
+ // Mojo service disconnection means the Cast Streaming Session ended and no
+ // further buffer will be received. kAborted will be returned to the media
+ // pipeline for every subsequent DemuxerStream::Read() attempt.
+ receiver_.set_disconnect_handler(base::BindOnce(
+ &CastStreamingDemuxerStream::OnMojoDisconnect, base::Unretained(this)));
+ }
+ ~CastStreamingDemuxerStream() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ }
+
+ // mojom::CastStreamingBufferReceiver implementation.
+ void ProvideBuffer(media::mojom::DecoderBufferPtr buffer) final {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ pending_buffer_metadata_.push_back(std::move(buffer));
+ GetNextBuffer();
+ }
+
+ void AbortPendingRead() {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (pending_read_cb_)
+ std::move(pending_read_cb_).Run(Status::kAborted, nullptr);
+ }
+
+ private:
+ void CompletePendingRead() {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!pending_read_cb_ || !current_buffer_)
+ return;
+
+ if (current_buffer_->end_of_stream()) {
+ std::move(pending_read_cb_).Run(Status::kAborted, nullptr);
+ return;
+ }
+
+ std::move(pending_read_cb_).Run(Status::kOk, std::move(current_buffer_));
+ GetNextBuffer();
+ }
+
+ void GetNextBuffer() {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (current_buffer_ || pending_buffer_metadata_.empty())
+ return;
+
+ media::mojom::DecoderBufferPtr buffer =
+ std::move(pending_buffer_metadata_.front());
+ pending_buffer_metadata_.pop_front();
+ decoder_buffer_reader_.ReadDecoderBuffer(
+ std::move(buffer),
+ base::BindOnce(&CastStreamingDemuxerStream::OnBufferRead,
+ base::Unretained(this)));
+ }
+
+ void OnBufferRead(scoped_refptr<media::DecoderBuffer> buffer) {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // Stop processing the pending buffer. OnMojoDisconnect() will trigger
+ // sending kAborted on subsequent Read() calls. This can happen if this
+ // object was in the process of reading a buffer off the data pipe when the
+ // Mojo connection ended.
+ if (!receiver_.is_bound())
+ return;
+
+ DCHECK(!current_buffer_);
+ current_buffer_ = buffer;
+ CompletePendingRead();
+ }
+
+ void OnMojoDisconnect() {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ receiver_.reset();
+ pending_buffer_metadata_.clear();
+ current_buffer_ = media::DecoderBuffer::CreateEOSBuffer();
+ CompletePendingRead();
+ }
+
+ // DemuxerStream implementation.
+ void Read(ReadCB read_cb) final {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(pending_read_cb_.is_null());
+ pending_read_cb_ = std::move(read_cb);
+ CompletePendingRead();
+ }
+ bool IsReadPending() const final { return !pending_read_cb_.is_null(); }
+ Liveness liveness() const final { return Liveness::LIVENESS_LIVE; }
+ bool SupportsConfigChanges() final { return false; }
+
+ mojo::Receiver<CastStreamingBufferReceiver> receiver_;
+ media::MojoDecoderBufferReader decoder_buffer_reader_;
+
+ ReadCB pending_read_cb_;
+ base::circular_deque<media::mojom::DecoderBufferPtr> pending_buffer_metadata_;
+ scoped_refptr<media::DecoderBuffer> current_buffer_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+};
+
+} // namespace
+
+class CastStreamingAudioDemuxerStream : public CastStreamingDemuxerStream {
+ public:
+ explicit CastStreamingAudioDemuxerStream(
+ mojom::AudioStreamInfoPtr audio_stream_info)
+ : CastStreamingDemuxerStream(
+ std::move(audio_stream_info->buffer_receiver),
+ std::move(audio_stream_info->data_pipe)),
+ config_(audio_stream_info->decoder_config) {
+ DVLOG(1) << __func__
+ << ": config info: " << config_.AsHumanReadableString();
+ }
+ ~CastStreamingAudioDemuxerStream() final = default;
+
+ private:
+ // DemuxerStream implementation.
+ media::AudioDecoderConfig audio_decoder_config() final { return config_; }
+ media::VideoDecoderConfig video_decoder_config() final {
+ NOTREACHED();
+ return media::VideoDecoderConfig();
+ }
+ Type type() const final { return Type::AUDIO; }
+
+ media::AudioDecoderConfig config_;
+};
+
+class CastStreamingVideoDemuxerStream : public CastStreamingDemuxerStream {
+ public:
+ explicit CastStreamingVideoDemuxerStream(
+ mojom::VideoStreamInfoPtr video_stream_info)
+ : CastStreamingDemuxerStream(
+ std::move(video_stream_info->buffer_receiver),
+ std::move(video_stream_info->data_pipe)),
+ config_(video_stream_info->decoder_config) {
+ DVLOG(1) << __func__
+ << ": config info: " << config_.AsHumanReadableString();
+ }
+ ~CastStreamingVideoDemuxerStream() final = default;
+
+ private:
+ // DemuxerStream implementation.
+ media::AudioDecoderConfig audio_decoder_config() final {
+ NOTREACHED();
+ return media::AudioDecoderConfig();
+ }
+ media::VideoDecoderConfig video_decoder_config() final { return config_; }
+ Type type() const final { return Type::VIDEO; }
+
+ media::VideoDecoderConfig config_;
+};
+
+CastStreamingDemuxer::CastStreamingDemuxer(
+ CastStreamingReceiver* receiver,
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner)
+ : media_task_runner_(media_task_runner),
+ original_task_runner_(base::SequencedTaskRunnerHandle::Get()),
+ receiver_(receiver) {
+ DVLOG(1) << __func__;
+ DCHECK(receiver_);
+}
+
+CastStreamingDemuxer::~CastStreamingDemuxer() {
+ DVLOG(1) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ if (was_initialization_successful_) {
+ original_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&CastStreamingReceiver::OnDemuxerDestroyed,
+ base::Unretained(receiver_)));
+ }
+}
+
+void CastStreamingDemuxer::OnStreamsInitialized(
+ mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info) {
+ DVLOG(1) << __func__;
+ DCHECK(!media_task_runner_->BelongsToCurrentThread());
+
+ media_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&CastStreamingDemuxer::OnStreamsInitializedOnMediaThread,
+ base::Unretained(this), std::move(audio_stream_info),
+ std::move(video_stream_info)));
+}
+
+void CastStreamingDemuxer::OnStreamsInitializedOnMediaThread(
+ mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info) {
+ DVLOG(1) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ DCHECK(initialized_cb_);
+
+ if (!audio_stream_info && !video_stream_info) {
+ std::move(initialized_cb_)
+ .Run(media::PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
+ return;
+ }
+
+ if (audio_stream_info) {
+ audio_stream_ = std::make_unique<CastStreamingAudioDemuxerStream>(
+ std::move(audio_stream_info));
+ }
+ if (video_stream_info) {
+ video_stream_ = std::make_unique<CastStreamingVideoDemuxerStream>(
+ std::move(video_stream_info));
+ }
+ was_initialization_successful_ = true;
+
+ std::move(initialized_cb_).Run(media::PipelineStatus::PIPELINE_OK);
+}
+
+std::vector<media::DemuxerStream*> CastStreamingDemuxer::GetAllStreams() {
+ DVLOG(1) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ std::vector<media::DemuxerStream*> streams;
+ if (video_stream_)
+ streams.push_back(video_stream_.get());
+ if (audio_stream_)
+ streams.push_back(audio_stream_.get());
+ return streams;
+}
+
+std::string CastStreamingDemuxer::GetDisplayName() const {
+ return "CastStreamingDemuxer";
+}
+
+void CastStreamingDemuxer::Initialize(media::DemuxerHost* host,
+ media::PipelineStatusCallback status_cb) {
+ DVLOG(1) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ host_ = host;
+
+ // Live streams have infinite duration.
+ host_->SetDuration(media::kInfiniteDuration);
+ initialized_cb_ = std::move(status_cb);
+
+ original_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&CastStreamingReceiver::SetDemuxer,
+ base::Unretained(receiver_), base::Unretained(this)));
+}
+
+void CastStreamingDemuxer::AbortPendingReads() {
+ DVLOG(2) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ if (audio_stream_)
+ audio_stream_->AbortPendingRead();
+ if (video_stream_)
+ video_stream_->AbortPendingRead();
+}
+
+// Not supported.
+void CastStreamingDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) {}
+
+// Not supported.
+void CastStreamingDemuxer::CancelPendingSeek(base::TimeDelta seek_time) {}
+
+// Not supported.
+void CastStreamingDemuxer::Seek(base::TimeDelta time,
+ media::PipelineStatusCallback status_cb) {
+ std::move(status_cb).Run(media::PipelineStatus::PIPELINE_OK);
+}
+
+void CastStreamingDemuxer::Stop() {
+ DVLOG(1) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ if (audio_stream_)
+ audio_stream_.reset();
+ if (video_stream_)
+ video_stream_.reset();
+}
+
+base::TimeDelta CastStreamingDemuxer::GetStartTime() const {
+ return base::TimeDelta();
+}
+
+// Not supported.
+base::Time CastStreamingDemuxer::GetTimelineOffset() const {
+ return base::Time();
+}
+
+// Not supported.
+int64_t CastStreamingDemuxer::GetMemoryUsage() const {
+ return 0;
+}
+
+base::Optional<media::container_names::MediaContainerName>
+CastStreamingDemuxer::GetContainerForMetrics() const {
+ // Cast Streaming frames have no container.
+ return base::nullopt;
+}
+
+// Not supported.
+void CastStreamingDemuxer::OnEnabledAudioTracksChanged(
+ const std::vector<media::MediaTrack::Id>& track_ids,
+ base::TimeDelta curr_time,
+ TrackChangeCB change_completed_cb) {
+ DLOG(WARNING) << "Track changes are not supported.";
+ std::vector<media::DemuxerStream*> streams;
+ std::move(change_completed_cb).Run(media::DemuxerStream::AUDIO, streams);
+}
+
+// Not supported.
+void CastStreamingDemuxer::OnSelectedVideoTrackChanged(
+ const std::vector<media::MediaTrack::Id>& track_ids,
+ base::TimeDelta curr_time,
+ TrackChangeCB change_completed_cb) {
+ DLOG(WARNING) << "Track changes are not supported.";
+ std::vector<media::DemuxerStream*> streams;
+ std::move(change_completed_cb).Run(media::DemuxerStream::VIDEO, streams);
+}
diff --git a/chromium/fuchsia/engine/renderer/cast_streaming_demuxer.h b/chromium/fuchsia/engine/renderer/cast_streaming_demuxer.h
new file mode 100644
index 00000000000..849320655bd
--- /dev/null
+++ b/chromium/fuchsia/engine/renderer/cast_streaming_demuxer.h
@@ -0,0 +1,84 @@
+// 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_ENGINE_RENDERER_CAST_STREAMING_DEMUXER_H_
+#define FUCHSIA_ENGINE_RENDERER_CAST_STREAMING_DEMUXER_H_
+
+#include "fuchsia/engine/cast_streaming_session.mojom.h"
+#include "media/base/demuxer.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+class CastStreamingReceiver;
+class CastStreamingAudioDemuxerStream;
+class CastStreamingVideoDemuxerStream;
+
+// media::Demuxer implementation for a Cast Streaming Receiver.
+// This object is instantiated on the main thread, whose task runner is stored
+// as |original_task_runner_|. OnStreamsInitialized() is the only method called
+// on the main thread. Every other method is called on the media thread, whose
+// task runner is |media_task_runner_|.
+// |original_task_runner_| is used to post method calls to |receiver_|, which is
+// guaranteed to outlive this object.
+// TODO(crbug.com/1082821): Simplify the CastStreamingDemuxer initialization
+// sequence when the CastStreamingReceiver Component has been implemented.
+class CastStreamingDemuxer : public media::Demuxer {
+ public:
+ CastStreamingDemuxer(
+ CastStreamingReceiver* receiver,
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner);
+ ~CastStreamingDemuxer() final;
+
+ CastStreamingDemuxer(const CastStreamingDemuxer&) = delete;
+ CastStreamingDemuxer& operator=(const CastStreamingDemuxer&) = delete;
+
+ void OnStreamsInitialized(mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info);
+
+ private:
+ void OnStreamsInitializedOnMediaThread(
+ mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info);
+
+ // media::Demuxer implementation.
+ std::vector<media::DemuxerStream*> GetAllStreams() final;
+ std::string GetDisplayName() const final;
+ void Initialize(media::DemuxerHost* host,
+ media::PipelineStatusCallback status_cb) final;
+ void AbortPendingReads() final;
+ void StartWaitingForSeek(base::TimeDelta seek_time) final;
+ void CancelPendingSeek(base::TimeDelta seek_time) final;
+ void Seek(base::TimeDelta time,
+ media::PipelineStatusCallback status_cb) final;
+ void Stop() final;
+ base::TimeDelta GetStartTime() const final;
+ base::Time GetTimelineOffset() const final;
+ int64_t GetMemoryUsage() const final;
+ base::Optional<media::container_names::MediaContainerName>
+ GetContainerForMetrics() const final;
+ void OnEnabledAudioTracksChanged(
+ const std::vector<media::MediaTrack::Id>& track_ids,
+ base::TimeDelta curr_time,
+ TrackChangeCB change_completed_cb) final;
+ void OnSelectedVideoTrackChanged(
+ const std::vector<media::MediaTrack::Id>& track_ids,
+ base::TimeDelta curr_time,
+ TrackChangeCB change_completed_cb) final;
+
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
+ scoped_refptr<base::SequencedTaskRunner> original_task_runner_;
+ media::DemuxerHost* host_ = nullptr;
+ std::unique_ptr<CastStreamingAudioDemuxerStream> audio_stream_;
+ std::unique_ptr<CastStreamingVideoDemuxerStream> video_stream_;
+
+ // Set to true if the Demuxer was successfully initialized.
+ bool was_initialization_successful_ = false;
+ media::PipelineStatusCallback initialized_cb_;
+ CastStreamingReceiver* const receiver_;
+};
+
+#endif // FUCHSIA_ENGINE_RENDERER_LIBCAST_STREAMING_DEMUXER_H_
diff --git a/chromium/fuchsia/engine/renderer/cast_streaming_receiver.cc b/chromium/fuchsia/engine/renderer/cast_streaming_receiver.cc
new file mode 100644
index 00000000000..98654200d90
--- /dev/null
+++ b/chromium/fuchsia/engine/renderer/cast_streaming_receiver.cc
@@ -0,0 +1,128 @@
+// 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/engine/renderer/cast_streaming_receiver.h"
+
+#include "content/public/renderer/render_frame.h"
+#include "fuchsia/engine/renderer/cast_streaming_demuxer.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
+
+CastStreamingReceiver::CastStreamingReceiver(
+ content::RenderFrame* render_frame) {
+ DVLOG(1) << __func__;
+ DCHECK(render_frame);
+
+ // It is fine to use an unretained pointer to |this| here as the
+ // AssociatedInterfaceRegistry, owned by |render_frame| will be torn-down at
+ // the same time as |this|.
+ render_frame->GetAssociatedInterfaceRegistry()->AddInterface(
+ base::BindRepeating(&CastStreamingReceiver::BindToReceiver,
+ base::Unretained(this)));
+}
+
+CastStreamingReceiver::~CastStreamingReceiver() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void CastStreamingReceiver::SetDemuxer(CastStreamingDemuxer* demuxer) {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(demuxer);
+
+ if (demuxer_) {
+ // We do not support more than one active CastStreamingDemuxer in the same
+ // RenderFrame. Return early here.
+ demuxer->OnStreamsInitialized(mojom::AudioStreamInfoPtr(),
+ mojom::VideoStreamInfoPtr());
+ return;
+ }
+
+ DCHECK(!is_demuxer_initialized_);
+
+ if (IsBound()) {
+ demuxer_ = demuxer;
+ MaybeCallEnableReceiverCallback();
+ } else {
+ // The Cast Streaming Sender disconnected after |demuxer| was instantiated
+ // but before |demuxer| was initialized on the media thread.
+ demuxer->OnStreamsInitialized(mojom::AudioStreamInfoPtr(),
+ mojom::VideoStreamInfoPtr());
+ }
+}
+
+void CastStreamingReceiver::OnDemuxerDestroyed() {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(demuxer_);
+
+ demuxer_ = nullptr;
+ is_demuxer_initialized_ = false;
+ cast_streaming_receiver_receiver_.reset();
+}
+
+void CastStreamingReceiver::BindToReceiver(
+ mojo::PendingAssociatedReceiver<mojom::CastStreamingReceiver> receiver) {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!cast_streaming_receiver_receiver_.is_bound());
+
+ cast_streaming_receiver_receiver_.Bind(std::move(receiver));
+
+ // Mojo service disconnection means the Cast Streaming Session ended or the
+ // Cast Streaming Sender disconnected.
+ cast_streaming_receiver_receiver_.set_disconnect_handler(base::BindOnce(
+ &CastStreamingReceiver::OnReceiverDisconnected, base::Unretained(this)));
+}
+
+bool CastStreamingReceiver::IsBound() const {
+ DVLOG(2) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ return cast_streaming_receiver_receiver_.is_bound();
+}
+
+void CastStreamingReceiver::MaybeCallEnableReceiverCallback() {
+ DVLOG(2) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (enable_receiver_callback_ && demuxer_)
+ std::move(enable_receiver_callback_).Run();
+}
+
+void CastStreamingReceiver::OnReceiverDisconnected() {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ cast_streaming_receiver_receiver_.reset();
+ enable_receiver_callback_.Reset();
+
+ if (demuxer_ && !is_demuxer_initialized_) {
+ OnStreamsInitialized(mojom::AudioStreamInfoPtr(),
+ mojom::VideoStreamInfoPtr());
+ }
+}
+
+void CastStreamingReceiver::EnableReceiver(EnableReceiverCallback callback) {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!enable_receiver_callback_);
+ DCHECK(callback);
+
+ enable_receiver_callback_ = std::move(callback);
+ MaybeCallEnableReceiverCallback();
+}
+
+void CastStreamingReceiver::OnStreamsInitialized(
+ mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info) {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!is_demuxer_initialized_);
+ DCHECK(demuxer_);
+
+ is_demuxer_initialized_ = true;
+ demuxer_->OnStreamsInitialized(std::move(audio_stream_info),
+ std::move(video_stream_info));
+}
diff --git a/chromium/fuchsia/engine/renderer/cast_streaming_receiver.h b/chromium/fuchsia/engine/renderer/cast_streaming_receiver.h
new file mode 100644
index 00000000000..a95a4aededf
--- /dev/null
+++ b/chromium/fuchsia/engine/renderer/cast_streaming_receiver.h
@@ -0,0 +1,63 @@
+// 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_ENGINE_RENDERER_CAST_STREAMING_RECEIVER_H_
+#define FUCHSIA_ENGINE_RENDERER_CAST_STREAMING_RECEIVER_H_
+
+#include "base/sequence_checker.h"
+#include "fuchsia/engine/cast_streaming_session.mojom.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+
+namespace content {
+class RenderFrame;
+} // namespace content
+
+class CastStreamingDemuxer;
+
+// Handles the Cast Streaming Session lifetime in the renderer process.
+// Owned by WebEngineRenderFrameObserver, this object will be destroyed on
+// RenderFrame destruction. This is guaranteed to outlive the
+// CastStreamingDemuxer that uses it as the RenderFrame destruction will have
+// triggered the destruction of the media pipeline and the CastStreamingDemuxer
+// before the call to content::RenderFrameObserver::OnDestruct(), which triggers
+// this object destruction.
+class CastStreamingReceiver : public mojom::CastStreamingReceiver {
+ public:
+ explicit CastStreamingReceiver(content::RenderFrame* frame);
+ ~CastStreamingReceiver() final;
+
+ CastStreamingReceiver(const CastStreamingReceiver&) = delete;
+ CastStreamingReceiver& operator=(const CastStreamingReceiver&) = delete;
+
+ void SetDemuxer(CastStreamingDemuxer* demuxer);
+ void OnDemuxerDestroyed();
+
+ // Returns true if a Mojo connection is active.
+ bool IsBound() const;
+
+ private:
+ void BindToReceiver(
+ mojo::PendingAssociatedReceiver<mojom::CastStreamingReceiver> receiver);
+
+ void MaybeCallEnableReceiverCallback();
+
+ void OnReceiverDisconnected();
+
+ // mojom::CastStreamingReceiver implementation.
+ void EnableReceiver(EnableReceiverCallback callback) final;
+ void OnStreamsInitialized(mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info) final;
+
+ mojo::AssociatedReceiver<mojom::CastStreamingReceiver>
+ cast_streaming_receiver_receiver_{this};
+
+ EnableReceiverCallback enable_receiver_callback_;
+ CastStreamingDemuxer* demuxer_ = nullptr;
+ bool is_demuxer_initialized_ = false;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+};
+
+#endif // FUCHSIA_ENGINE_RENDERER_CAST_STREAMING_RECEIVER_H_
diff --git a/chromium/fuchsia/engine/renderer/on_load_script_injector.cc b/chromium/fuchsia/engine/renderer/on_load_script_injector.cc
index b966fbacc1e..6fd0a6db314 100644
--- a/chromium/fuchsia/engine/renderer/on_load_script_injector.cc
+++ b/chromium/fuchsia/engine/renderer/on_load_script_injector.cc
@@ -28,12 +28,7 @@ void OnLoadScriptInjector::BindToReceiver(
}
void OnLoadScriptInjector::DidCommitProvisionalLoad(
- bool is_same_document_navigation,
ui::PageTransition transition) {
- // Ignore pushState or document fragment navigation.
- if (is_same_document_navigation)
- return;
-
// Don't inject anything for subframes.
if (!render_frame()->IsMainFrame())
return;
diff --git a/chromium/fuchsia/engine/renderer/on_load_script_injector.h b/chromium/fuchsia/engine/renderer/on_load_script_injector.h
index 80bd6b98d76..3e5364e8948 100644
--- a/chromium/fuchsia/engine/renderer/on_load_script_injector.h
+++ b/chromium/fuchsia/engine/renderer/on_load_script_injector.h
@@ -30,8 +30,7 @@ class OnLoadScriptInjector : public content::RenderFrameObserver,
// RenderFrameObserver override:
void OnDestruct() override;
- void DidCommitProvisionalLoad(bool is_same_document_navigation,
- ui::PageTransition transition) override;
+ void DidCommitProvisionalLoad(ui::PageTransition transition) override;
private:
// Called by OnDestruct(), when the RenderFrame is destroyed.
diff --git a/chromium/fuchsia/engine/renderer/url_request_rules_receiver.cc b/chromium/fuchsia/engine/renderer/url_request_rules_receiver.cc
index 0b0874954d0..c1da8c7bb99 100644
--- a/chromium/fuchsia/engine/renderer/url_request_rules_receiver.cc
+++ b/chromium/fuchsia/engine/renderer/url_request_rules_receiver.cc
@@ -11,13 +11,8 @@
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
UrlRequestRulesReceiver::UrlRequestRulesReceiver(
- content::RenderFrame* render_frame,
- base::OnceCallback<void(int)> on_render_frame_deleted_callback)
- : content::RenderFrameObserver(render_frame),
- on_render_frame_deleted_callback_(
- std::move(on_render_frame_deleted_callback)) {
+ content::RenderFrame* render_frame) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(on_render_frame_deleted_callback_);
DCHECK(render_frame);
// It is fine to use an unretained pointer to |this| here as the
@@ -54,12 +49,3 @@ UrlRequestRulesReceiver::GetCachedRules() {
base::AutoLock auto_lock(lock_);
return cached_rules_;
}
-
-void UrlRequestRulesReceiver::OnDestruct() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- // The RenderFrame corresponding to this object was destroyed, which means
- // the AssociatedInterfaceRegsitry is also gone. It is expected that
- // |on_render_frame_deleted_callback_| will delete |this|.
- std::move(on_render_frame_deleted_callback_).Run(routing_id());
-}
diff --git a/chromium/fuchsia/engine/renderer/url_request_rules_receiver.h b/chromium/fuchsia/engine/renderer/url_request_rules_receiver.h
index 8b2db7b10c1..98125825f38 100644
--- a/chromium/fuchsia/engine/renderer/url_request_rules_receiver.h
+++ b/chromium/fuchsia/engine/renderer/url_request_rules_receiver.h
@@ -19,22 +19,18 @@ namespace content {
class RenderFrame;
} // namespace content
-// Provides rewriting rules for network requests. UrlRequestRulesReceiver
-// objects are owned by their respective WebEngineContentRendererClient and they
-// will be destroyed on RenderFrame destruction. This is guaranteed to outlive
-// any WebEngineURLLoaderThrottle that uses it as the RenderFrame destruction
-// will have triggered the destruction of all pending
-// WebEngineURLLoaderThrottles.
+// Provides rewriting rules for network requests. Owned by
+// WebEngineRenderFrameObserver, this object will be destroyed on RenderFrame
+// destruction. This is guaranteed to outlive any WebEngineURLLoaderThrottle
+// that uses it as the RenderFrame destruction will have triggered the
+// destruction of all pending WebEngineURLLoaderThrottles.
// This class should only be used on the IO thread, with the exception of the
// GetCachedRules() implementation, which can be called from any sequence.
class UrlRequestRulesReceiver
: public mojom::UrlRequestRulesReceiver,
- public WebEngineURLLoaderThrottle::CachedRulesProvider,
- public content::RenderFrameObserver {
+ public WebEngineURLLoaderThrottle::CachedRulesProvider {
public:
- UrlRequestRulesReceiver(
- content::RenderFrame* render_frame,
- base::OnceCallback<void(int)> on_render_frame_deleted_callback);
+ UrlRequestRulesReceiver(content::RenderFrame* render_frame);
~UrlRequestRulesReceiver() override;
private:
@@ -48,9 +44,6 @@ class UrlRequestRulesReceiver
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
GetCachedRules() override;
- // content::RenderFrameObserver implementation.
- void OnDestruct() override;
-
base::Lock lock_;
// This is accessed by WebEngineURLLoaderThrottles, which can be off-sequence
@@ -61,7 +54,6 @@ class UrlRequestRulesReceiver
mojo::AssociatedReceiver<mojom::UrlRequestRulesReceiver>
url_request_rules_receiver_{this};
- base::OnceCallback<void(int)> on_render_frame_deleted_callback_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(UrlRequestRulesReceiver);
diff --git a/chromium/fuchsia/engine/renderer/web_engine_content_renderer_client.cc b/chromium/fuchsia/engine/renderer/web_engine_content_renderer_client.cc
index 2fc77c0d567..35d3f37a2fd 100644
--- a/chromium/fuchsia/engine/renderer/web_engine_content_renderer_client.cc
+++ b/chromium/fuchsia/engine/renderer/web_engine_content_renderer_client.cc
@@ -9,6 +9,8 @@
#include "components/cdm/renderer/widevine_key_system_properties.h"
#include "components/media_control/renderer/media_playback_options.h"
#include "content/public/renderer/render_frame.h"
+#include "fuchsia/engine/common/cast_streaming.h"
+#include "fuchsia/engine/renderer/cast_streaming_demuxer.h"
#include "fuchsia/engine/renderer/on_load_script_injector.h"
#include "fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.h"
#include "fuchsia/engine/switches.h"
@@ -110,16 +112,16 @@ WebEngineContentRendererClient::WebEngineContentRendererClient() = default;
WebEngineContentRendererClient::~WebEngineContentRendererClient() = default;
-UrlRequestRulesReceiver*
-WebEngineContentRendererClient::GetUrlRequestRulesReceiverForRenderFrameId(
+WebEngineRenderFrameObserver*
+WebEngineContentRendererClient::GetWebEngineRenderFrameObserverForRenderFrameId(
int render_frame_id) const {
- auto iter = url_request_receivers_by_id_.find(render_frame_id);
- DCHECK(iter != url_request_receivers_by_id_.end());
+ auto iter = render_frame_id_to_observer_map_.find(render_frame_id);
+ DCHECK(iter != render_frame_id_to_observer_map_.end());
return iter->second.get();
}
void WebEngineContentRendererClient::OnRenderFrameDeleted(int render_frame_id) {
- size_t count = url_request_receivers_by_id_.erase(render_frame_id);
+ size_t count = render_frame_id_to_observer_map_.erase(render_frame_id);
DCHECK_EQ(count, 1u);
}
@@ -130,13 +132,14 @@ void WebEngineContentRendererClient::RenderFrameCreated(
new OnLoadScriptInjector(render_frame);
int render_frame_id = render_frame->GetRoutingID();
- auto rules_receiver = std::make_unique<UrlRequestRulesReceiver>(
- content::RenderFrame::FromRoutingID(render_frame_id),
+
+ auto render_frame_observer = std::make_unique<WebEngineRenderFrameObserver>(
+ render_frame,
base::BindOnce(&WebEngineContentRendererClient::OnRenderFrameDeleted,
base::Unretained(this)));
- auto iter = url_request_receivers_by_id_.emplace(render_frame_id,
- std::move(rules_receiver));
- DCHECK(iter.second);
+ auto render_frame_observer_iter = render_frame_id_to_observer_map_.emplace(
+ render_frame_id, std::move(render_frame_observer));
+ DCHECK(render_frame_observer_iter.second);
// Lifetime is tied to |render_frame| via content::RenderFrameObserver.
new media_control::MediaPlaybackOptions(render_frame);
@@ -235,6 +238,30 @@ bool WebEngineContentRendererClient::DeferMediaLoad(
return RunClosureWhenInForeground(render_frame, std::move(closure));
}
+std::unique_ptr<media::Demuxer>
+WebEngineContentRendererClient::OverrideDemuxerForUrl(
+ content::RenderFrame* render_frame,
+ const GURL& url,
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner) {
+ if (IsCastStreamingEnabled() && IsCastStreamingMediaSourceUrl(url)) {
+ auto iter =
+ render_frame_id_to_observer_map_.find(render_frame->GetRoutingID());
+ DCHECK(iter != render_frame_id_to_observer_map_.end());
+ // Do not create a CastStreamingDemuxer if the Cast Streaming MessagePort
+ // was not set in the browser process. This will manifest as an unbound
+ // CastStreamingReceiver object in the renderer process.
+ // TODO(crbug.com/1082821): Simplify the instantiation conditions for the
+ // CastStreamingDemuxer once the CastStreamingReceiver Component has been
+ // implemented.
+ if (iter->second->cast_streaming_receiver()->IsBound()) {
+ return std::make_unique<CastStreamingDemuxer>(
+ iter->second->cast_streaming_receiver(), media_task_runner);
+ }
+ }
+
+ return nullptr;
+}
+
bool WebEngineContentRendererClient::RunClosureWhenInForeground(
content::RenderFrame* render_frame,
base::OnceClosure closure) {
diff --git a/chromium/fuchsia/engine/renderer/web_engine_content_renderer_client.h b/chromium/fuchsia/engine/renderer/web_engine_content_renderer_client.h
index 93b3a110a9e..8c16a116bef 100644
--- a/chromium/fuchsia/engine/renderer/web_engine_content_renderer_client.h
+++ b/chromium/fuchsia/engine/renderer/web_engine_content_renderer_client.h
@@ -7,20 +7,21 @@
#include "base/macros.h"
#include "content/public/renderer/content_renderer_client.h"
-#include "fuchsia/engine/renderer/url_request_rules_receiver.h"
+#include "fuchsia/engine/renderer/web_engine_render_frame_observer.h"
class WebEngineContentRendererClient : public content::ContentRendererClient {
public:
WebEngineContentRendererClient();
~WebEngineContentRendererClient() override;
- // Returns the UrlRequestRulesReceiver corresponding to |render_frame_id|.
- UrlRequestRulesReceiver* GetUrlRequestRulesReceiverForRenderFrameId(
+ // Returns the WebEngineRenderFrameObserver corresponding to
+ // |render_frame_id|.
+ WebEngineRenderFrameObserver* GetWebEngineRenderFrameObserverForRenderFrameId(
int render_frame_id) const;
private:
- // Called by UrlRequestRulesReceivers when their corresponding RenderFrame is
- // in the process of being deleted.
+ // Called by WebEngineRenderFrameObserver when its corresponding RenderFrame
+ // is in the process of being deleted.
void OnRenderFrameDeleted(int render_frame_id);
// content::ContentRendererClient overrides.
@@ -35,13 +36,17 @@ class WebEngineContentRendererClient : public content::ContentRendererClient {
bool DeferMediaLoad(content::RenderFrame* render_frame,
bool has_played_media_before,
base::OnceClosure closure) override;
+ std::unique_ptr<media::Demuxer> OverrideDemuxerForUrl(
+ content::RenderFrame* render_frame,
+ const GURL& url,
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner) override;
bool RunClosureWhenInForeground(content::RenderFrame* render_frame,
base::OnceClosure closure);
- // Map of rules receivers per RenderFrame ID.
- std::map<int, std::unique_ptr<UrlRequestRulesReceiver>>
- url_request_receivers_by_id_;
+ // Map of RenderFrame ID to WebEngineRenderFrameObserver.
+ std::map<int, std::unique_ptr<WebEngineRenderFrameObserver>>
+ render_frame_id_to_observer_map_;
DISALLOW_COPY_AND_ASSIGN(WebEngineContentRendererClient);
};
diff --git a/chromium/fuchsia/engine/renderer/web_engine_render_frame_observer.cc b/chromium/fuchsia/engine/renderer/web_engine_render_frame_observer.cc
new file mode 100644
index 00000000000..8120227565b
--- /dev/null
+++ b/chromium/fuchsia/engine/renderer/web_engine_render_frame_observer.cc
@@ -0,0 +1,25 @@
+// 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/engine/renderer/web_engine_render_frame_observer.h"
+
+#include "content/public/renderer/render_frame.h"
+
+WebEngineRenderFrameObserver::WebEngineRenderFrameObserver(
+ content::RenderFrame* render_frame,
+ base::OnceCallback<void(int)> on_render_frame_deleted_callback)
+ : content::RenderFrameObserver(render_frame),
+ url_request_rules_receiver_(render_frame),
+ cast_streaming_receiver_(render_frame),
+ on_render_frame_deleted_callback_(
+ std::move(on_render_frame_deleted_callback)) {
+ DCHECK(render_frame);
+ DCHECK(on_render_frame_deleted_callback_);
+}
+
+WebEngineRenderFrameObserver::~WebEngineRenderFrameObserver() = default;
+
+void WebEngineRenderFrameObserver::OnDestruct() {
+ std::move(on_render_frame_deleted_callback_).Run(routing_id());
+}
diff --git a/chromium/fuchsia/engine/renderer/web_engine_render_frame_observer.h b/chromium/fuchsia/engine/renderer/web_engine_render_frame_observer.h
new file mode 100644
index 00000000000..5e3f5c5c8fe
--- /dev/null
+++ b/chromium/fuchsia/engine/renderer/web_engine_render_frame_observer.h
@@ -0,0 +1,50 @@
+// 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_ENGINE_RENDERER_WEB_ENGINE_RENDER_FRAME_OBSERVER_H_
+#define FUCHSIA_ENGINE_RENDERER_WEB_ENGINE_RENDER_FRAME_OBSERVER_H_
+
+#include "base/callback.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "fuchsia/engine/renderer/cast_streaming_receiver.h"
+#include "fuchsia/engine/renderer/url_request_rules_receiver.h"
+
+namespace content {
+class RenderFrame;
+} // namespace content
+
+// This class owns WebEngine-specific objects whose lifespan is tied to a
+// RenderFrame. Owned by WebEngineContentRendererClient, this object will be
+// destroyed on RenderFrame destruction, triggering the destruction of all of
+// the objects it exposes.
+class WebEngineRenderFrameObserver : public content::RenderFrameObserver {
+ public:
+ // |on_render_frame_deleted_callback| must delete |this|.
+ WebEngineRenderFrameObserver(
+ content::RenderFrame* render_frame,
+ base::OnceCallback<void(int)> on_render_frame_deleted_callback);
+ ~WebEngineRenderFrameObserver() final;
+
+ WebEngineRenderFrameObserver(const WebEngineRenderFrameObserver&) = delete;
+ WebEngineRenderFrameObserver& operator=(const WebEngineRenderFrameObserver&) =
+ delete;
+
+ UrlRequestRulesReceiver* url_request_rules_receiver() {
+ return &url_request_rules_receiver_;
+ }
+ CastStreamingReceiver* cast_streaming_receiver() {
+ return &cast_streaming_receiver_;
+ }
+
+ private:
+ // content::RenderFrameObserver implementation.
+ void OnDestruct() final;
+
+ UrlRequestRulesReceiver url_request_rules_receiver_;
+ CastStreamingReceiver cast_streaming_receiver_;
+
+ base::OnceCallback<void(int)> on_render_frame_deleted_callback_;
+};
+
+#endif // FUCHSIA_ENGINE_RENDERER_WEB_ENGINE_RENDER_FRAME_OBSERVER_H_
diff --git a/chromium/fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.cc b/chromium/fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.cc
index 5b24b461406..95e8e64d510 100644
--- a/chromium/fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.cc
+++ b/chromium/fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.cc
@@ -33,8 +33,9 @@ WebEngineURLLoaderThrottleProvider::CreateThrottles(
std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
throttles.emplace_back(std::make_unique<WebEngineURLLoaderThrottle>(
- content_renderer_client_->GetUrlRequestRulesReceiverForRenderFrameId(
- render_frame_id)));
+ content_renderer_client_
+ ->GetWebEngineRenderFrameObserverForRenderFrameId(render_frame_id)
+ ->url_request_rules_receiver()));
return throttles;
}
diff --git a/chromium/fuchsia/engine/web_engine_debug_integration_test.cc b/chromium/fuchsia/engine/web_engine_debug_integration_test.cc
index 3dd1fe35fad..185ac678c6f 100644
--- a/chromium/fuchsia/engine/web_engine_debug_integration_test.cc
+++ b/chromium/fuchsia/engine/web_engine_debug_integration_test.cc
@@ -10,7 +10,6 @@
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/file_utils.h"
#include "base/macros.h"
#include "base/test/task_environment.h"
@@ -65,8 +64,7 @@ class WebEngineDebugIntegrationTest : public testing::Test {
base::FileEnumerator file_enum(
base::FilePath("/hub/c/context_provider.cmx"), false,
base::FileEnumerator::DIRECTORIES);
- base::FilePath web_engine_path = file_enum.Next();
- ASSERT_FALSE(web_engine_path.empty());
+ base::FilePath web_engine_path;
for (auto dir = file_enum.Next(); !dir.empty(); dir = file_enum.Next()) {
std::string args;
diff --git a/chromium/fuchsia/engine/web_engine_integration_test.cc b/chromium/fuchsia/engine/web_engine_integration_test.cc
index 685698c3e4c..3b250cf5d4d 100644
--- a/chromium/fuchsia/engine/web_engine_integration_test.cc
+++ b/chromium/fuchsia/engine/web_engine_integration_test.cc
@@ -11,10 +11,10 @@
#include "base/command_line.h"
#include "base/files/file_enumerator.h"
-#include "base/fuchsia/default_context.h"
#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/fuchsia/scoped_service_binding.h"
#include "base/macros.h"
#include "base/path_service.h"
@@ -105,7 +105,7 @@ class WebEngineIntegrationTest : public testing::Test {
ContextParamsWithFilteredServiceDirectory() {
filtered_service_directory_ =
std::make_unique<base::fuchsia::FilteredServiceDirectory>(
- base::fuchsia::ComponentContextForCurrentProcess()->svc().get());
+ base::ComponentContextForProcess()->svc().get());
fidl::InterfaceHandle<fuchsia::io::Directory> svc_dir;
filtered_service_directory_->ConnectClient(svc_dir.NewRequest());
@@ -121,6 +121,31 @@ class WebEngineIntegrationTest : public testing::Test {
return create_params;
}
+ // Returns CreateContextParams that has AUDIO feature enabled with an injected
+ // FakeAudioConsumerService.
+ fuchsia::web::CreateContextParams ContextParamsWithAudio() {
+ // Use a FilteredServiceDirectory in order to inject a fake AudioConsumer
+ // service.
+ fuchsia::web::CreateContextParams create_params =
+ ContextParamsWithFilteredServiceDirectory();
+
+ fake_audio_consumer_service_ =
+ std::make_unique<media::FakeAudioConsumerService>(
+ filtered_service_directory_->outgoing_directory()
+ ->GetOrCreateDirectory("svc"));
+
+ create_params.set_features(fuchsia::web::ContextFeatureFlags::AUDIO);
+
+ return create_params;
+ }
+
+ fuchsia::web::CreateContextParams ContextParamsWithAudioAndTestData() {
+ fuchsia::web::CreateContextParams create_params = ContextParamsWithAudio();
+ create_params.mutable_content_directories()->push_back(
+ CreateTestDataDirectoryProvider());
+ return create_params;
+ }
+
void CreateNavigationListener() {
// Attach a navigation listener, to monitor the state of the Frame.
navigation_listener_ =
@@ -170,6 +195,12 @@ class WebEngineIntegrationTest : public testing::Test {
navigation_listener_->RunUntilUrlEquals(url);
}
+ void LoadUrlWithUserActivation(base::StringPiece url) {
+ EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
+ navigation_controller_.get(),
+ cr_fuchsia::CreateLoadUrlParamsWithUserActivation(), url));
+ }
+
void GrantPermission(fuchsia::web::PermissionType type,
const std::string& origin) {
fuchsia::web::PermissionDescriptor permission;
@@ -218,6 +249,8 @@ class WebEngineIntegrationTest : public testing::Test {
std::unique_ptr<base::fuchsia::FilteredServiceDirectory>
filtered_service_directory_;
+ std::unique_ptr<media::FakeAudioConsumerService> fake_audio_consumer_service_;
+
DISALLOW_COPY_AND_ASSIGN(WebEngineIntegrationTest);
};
@@ -470,41 +503,37 @@ TEST_F(WebEngineIntegrationTest, ContentDirectoryProvider) {
TEST_F(WebEngineIntegrationTest, PlayAudio) {
StartWebEngine();
-
- // Use a FilteredServiceDirectory in order to inject a fake AudioConsumer
- // service.
- fuchsia::web::CreateContextParams create_params =
- ContextParamsWithFilteredServiceDirectory();
-
- media::FakeAudioConsumerService fake_audio_consumer_service(
- filtered_service_directory_->outgoing_directory()->GetOrCreateDirectory(
- "svc"));
-
- create_params.mutable_content_directories()->push_back(
- CreateTestDataDirectoryProvider());
- create_params.set_features(fuchsia::web::ContextFeatureFlags::AUDIO);
- CreateContextAndFrame(std::move(create_params));
+ CreateContextAndFrame(ContextParamsWithAudioAndTestData());
static uint16_t kTestMediaSessionId = 43;
frame_->SetMediaSessionId(kTestMediaSessionId);
- EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
- navigation_controller_.get(),
- cr_fuchsia::CreateLoadUrlParamsWithUserActivation(),
- "fuchsia-dir://testdata/play_audio.html"));
+ LoadUrlWithUserActivation("fuchsia-dir://testdata/play_audio.html");
navigation_listener_->RunUntilTitleEquals("ended");
- ASSERT_EQ(fake_audio_consumer_service.num_instances(), 1U);
+ ASSERT_EQ(fake_audio_consumer_service_->num_instances(), 1U);
- auto pos = fake_audio_consumer_service.instance(0)->GetMediaPosition();
+ auto pos = fake_audio_consumer_service_->instance(0)->GetMediaPosition();
EXPECT_GT(pos, base::TimeDelta::FromSecondsD(2.0));
EXPECT_LT(pos, base::TimeDelta::FromSecondsD(2.5));
- EXPECT_EQ(fake_audio_consumer_service.instance(0)->session_id(),
+ EXPECT_EQ(fake_audio_consumer_service_->instance(0)->session_id(),
kTestMediaSessionId);
- EXPECT_EQ(fake_audio_consumer_service.instance(0)->volume(), 1.0);
- EXPECT_FALSE(fake_audio_consumer_service.instance(0)->is_muted());
+ EXPECT_EQ(fake_audio_consumer_service_->instance(0)->volume(), 1.0);
+ EXPECT_FALSE(fake_audio_consumer_service_->instance(0)->is_muted());
+}
+
+// TODO(crbug.com/1090159): Reenable when cadence estimator DCHECK is fixed.
+TEST_F(WebEngineIntegrationTest, DISABLED_PlayVideo) {
+ StartWebEngine();
+ CreateContextAndFrame(ContextParamsWithAudioAndTestData());
+
+ frame_->SetBlockMediaLoading(false);
+
+ LoadUrlWithUserActivation("fuchsia-dir://testdata/play_video.html?autoplay");
+
+ navigation_listener_->RunUntilTitleEquals("ended");
}
void WebEngineIntegrationTest::RunPermissionTest(bool grant) {
@@ -536,10 +565,7 @@ TEST_F(WebEngineIntegrationTest, PermissionGranted) {
TEST_F(WebEngineIntegrationTest, MicrophoneAccess_WithPermission) {
StartWebEngine();
-
- fuchsia::web::CreateContextParams create_params = DefaultContextParams();
- create_params.set_features(fuchsia::web::ContextFeatureFlags::AUDIO);
- CreateContextAndFrame(std::move(create_params));
+ CreateContextAndFrame(ContextParamsWithAudio());
GrantPermission(fuchsia::web::PermissionType::MICROPHONE,
embedded_test_server_.GetURL("/").GetOrigin().spec());
@@ -553,10 +579,7 @@ TEST_F(WebEngineIntegrationTest, MicrophoneAccess_WithPermission) {
TEST_F(WebEngineIntegrationTest, MicrophoneAccess_WithoutPermission) {
StartWebEngine();
-
- fuchsia::web::CreateContextParams create_params = DefaultContextParams();
- create_params.set_features(fuchsia::web::ContextFeatureFlags::AUDIO);
- CreateContextAndFrame(std::move(create_params));
+ CreateContextAndFrame(ContextParamsWithAudio());
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
navigation_controller_.get(), fuchsia::web::LoadUrlParams(),
@@ -565,21 +588,14 @@ TEST_F(WebEngineIntegrationTest, MicrophoneAccess_WithoutPermission) {
navigation_listener_->RunUntilTitleEquals("ended");
}
-TEST_F(WebEngineIntegrationTest, SetBlockMediaLoading_Blocked) {
+// TODO(crbug.com/1090159): Reenable when cadence estimator DCHECK is fixed.
+TEST_F(WebEngineIntegrationTest, DISABLED_SetBlockMediaLoading_Blocked) {
StartWebEngine();
-
- fuchsia::web::CreateContextParams create_params =
- DefaultContextParamsWithTestData();
- auto features = fuchsia::web::ContextFeatureFlags::AUDIO;
- create_params.set_features(features);
- CreateContextAndFrame(std::move(create_params));
+ CreateContextAndFrame(ContextParamsWithAudioAndTestData());
frame_->SetBlockMediaLoading(true);
- EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
- navigation_controller_.get(),
- cr_fuchsia::CreateLoadUrlParamsWithUserActivation(),
- "fuchsia-dir://testdata/play_vp8.html?autoplay"));
+ LoadUrlWithUserActivation("fuchsia-dir://testdata/play_video.html?autoplay");
// Check different indicators that media has not loaded and is not playing.
navigation_listener_->RunUntilTitleEquals("stalled");
@@ -591,21 +607,14 @@ TEST_F(WebEngineIntegrationTest, SetBlockMediaLoading_Blocked) {
// Initially, set media blocking to be true. When media is unblocked, check that
// it begins playing, since autoplay=true.
-TEST_F(WebEngineIntegrationTest, SetBlockMediaLoading_AfterUnblock) {
+// TODO(crbug.com/1090159): Reenable when cadence estimator DCHECK is fixed.
+TEST_F(WebEngineIntegrationTest, DISABLED_SetBlockMediaLoading_AfterUnblock) {
StartWebEngine();
-
- fuchsia::web::CreateContextParams create_params =
- DefaultContextParamsWithTestData();
- auto features = fuchsia::web::ContextFeatureFlags::AUDIO;
- create_params.set_features(features);
- CreateContextAndFrame(std::move(create_params));
+ CreateContextAndFrame(ContextParamsWithAudioAndTestData());
frame_->SetBlockMediaLoading(true);
- EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
- navigation_controller_.get(),
- cr_fuchsia::CreateLoadUrlParamsWithUserActivation(),
- "fuchsia-dir://testdata/play_vp8.html?autoplay"));
+ LoadUrlWithUserActivation("fuchsia-dir://testdata/play_video.html?autoplay");
// Check that media loading has been blocked.
navigation_listener_->RunUntilTitleEquals("stalled");
@@ -619,19 +628,13 @@ TEST_F(WebEngineIntegrationTest, SetBlockMediaLoading_AfterUnblock) {
// Check that when autoplay=false and media loading was blocked after the
// element has started loading that media will play when play() is called.
-TEST_F(WebEngineIntegrationTest, SetBlockMediaLoading_SetBlockedAfterLoading) {
+// TODO(crbug.com/1090159): Reenable when cadence estimator DCHECK is fixed.
+TEST_F(WebEngineIntegrationTest,
+ DISABLED_SetBlockMediaLoading_SetBlockedAfterLoading) {
StartWebEngine();
+ CreateContextAndFrame(ContextParamsWithAudioAndTestData());
- fuchsia::web::CreateContextParams create_params =
- DefaultContextParamsWithTestData();
- auto features = fuchsia::web::ContextFeatureFlags::AUDIO;
- create_params.set_features(features);
- CreateContextAndFrame(std::move(create_params));
-
- EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
- navigation_controller_.get(),
- cr_fuchsia::CreateLoadUrlParamsWithUserActivation(),
- "fuchsia-dir://testdata/play_vp8.html"));
+ LoadUrlWithUserActivation("fuchsia-dir://testdata/play_video.html");
navigation_listener_->RunUntilTitleEquals("loaded");
frame_->SetBlockMediaLoading(true);
diff --git a/chromium/fuchsia/engine/web_engine_integration_tests.cmx b/chromium/fuchsia/engine/web_engine_integration_tests.cmx
index 13c1bca70be..7ab18a4b3c2 100644
--- a/chromium/fuchsia/engine/web_engine_integration_tests.cmx
+++ b/chromium/fuchsia/engine/web_engine_integration_tests.cmx
@@ -13,6 +13,7 @@
"fuchsia.logger.LogSink",
"fuchsia.media.Audio",
"fuchsia.media.SessionAudioConsumerFactory",
+ "fuchsia.memorypressure.Provider",
"fuchsia.net.NameLookup",
"fuchsia.netstack.Netstack",
"fuchsia.posix.socket.Provider",
diff --git a/chromium/fuchsia/fidl/cast/application_context.fidl b/chromium/fuchsia/fidl/cast/application_context.fidl
index 3b8b284dc85..4a1027a6092 100644
--- a/chromium/fuchsia/fidl/cast/application_context.fidl
+++ b/chromium/fuchsia/fidl/cast/application_context.fidl
@@ -12,4 +12,11 @@ protocol ApplicationContext {
/// Used by the Agent to receive a controller from the Cast Runner.
/// Can only be called at most one time for the lifetime of the Component.
SetApplicationController(ApplicationController controller);
+
+ /// Called if the application component exits gracefully, with the same
+ /// `exit_code` as would be reported via `ComponentController.OnTerminated()`.
+ /// Values less than or equal to zero are `zx.status` codes.
+ /// May be called at most once, immediately prior to termination.
+ [Transitional]
+ OnApplicationExit(int64 exit_code);
};
diff --git a/chromium/fuchsia/http/http_service_main.cc b/chromium/fuchsia/http/http_service_main.cc
index 359a15bb84e..6df26c0b1f0 100644
--- a/chromium/fuchsia/http/http_service_main.cc
+++ b/chromium/fuchsia/http/http_service_main.cc
@@ -7,7 +7,7 @@
#include "base/at_exit.h"
#include "base/bind.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/run_loop.h"
@@ -25,7 +25,7 @@ int main(int argc, char** argv) {
// Bind the parent-supplied OutgoingDirectory-request to a directory and
// publish the HTTP service into it.
sys::OutgoingDirectory* outgoing_directory =
- base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get();
+ base::ComponentContextForProcess()->outgoing().get();
HttpServiceImpl http_service;
base::fuchsia::ScopedServiceBinding<::fuchsia::net::oldhttp::HttpService>
binding(outgoing_directory, &http_service);
@@ -36,7 +36,7 @@ int main(int argc, char** argv) {
// connected to this service. The system service manager will restart the
// service on demand as needed.
binding.SetOnLastClientCallback(
- base::BindOnce(&base::RunLoop::Quit, base::Unretained(&run_loop)));
+ base::BindRepeating(&base::RunLoop::Quit, base::Unretained(&run_loop)));
run_loop.Run();
return 0;
diff --git a/chromium/fuchsia/mojom/BUILD.gn b/chromium/fuchsia/mojom/BUILD.gn
index d06caabf100..ed7c1eb4f85 100644
--- a/chromium/fuchsia/mojom/BUILD.gn
+++ b/chromium/fuchsia/mojom/BUILD.gn
@@ -10,6 +10,26 @@ import("//testing/test.gni")
mojom("example_interfaces") {
testonly = true
sources = [ "example.mojom" ]
+ cpp_typemaps = [
+ {
+ types = [
+ {
+ mojom = "fuchsia.test.mojom.TestInterfaceRequest"
+ cpp = "::fidl::InterfaceRequest<::base::fuchsia::testfidl::TestInterface>"
+ move_only = true
+ },
+ ]
+
+ traits_headers = [
+ "//base/fuchsia/testfidl/cpp/fidl.h",
+ "//fuchsia/mojom/test_interface_request_mojom_traits.h",
+ ]
+ traits_public_deps = [
+ ":traits",
+ "//base:testfidl",
+ ]
+ },
+ ]
}
source_set("traits") {
diff --git a/chromium/fuchsia/mojom/OWNERS b/chromium/fuchsia/mojom/OWNERS
index ae29a36aac8..1feb5149750 100644
--- a/chromium/fuchsia/mojom/OWNERS
+++ b/chromium/fuchsia/mojom/OWNERS
@@ -2,5 +2,3 @@ per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
per-file *_mojom_traits*.*=set noparent
per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *.typemap=set noparent
-per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromium/fuchsia/mojom/example.typemap b/chromium/fuchsia/mojom/example.typemap
deleted file mode 100644
index 7e2aaac3df0..00000000000
--- a/chromium/fuchsia/mojom/example.typemap
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2019 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.
-
-mojom = "//fuchsia/mojom/example.mojom"
-os_whitelist = [ "fuchsia" ]
-public_headers = [ "base/fuchsia/testfidl/cpp/fidl.h" ]
-traits_headers = [ "//fuchsia/mojom/test_interface_request_mojom_traits.h" ]
-sources = [
- "//fuchsia/mojom/test_interface_request_mojom_traits.h",
-]
-public_deps = [
- "//base:testfidl",
- "//fuchsia/mojom:traits",
-]
-type_mappings = [ "fuchsia.test.mojom.TestInterfaceRequest=::fidl::InterfaceRequest<::base::fuchsia::testfidl::TestInterface>[move_only]" ]
diff --git a/chromium/fuchsia/mojom/test_typemaps.gni b/chromium/fuchsia/mojom/test_typemaps.gni
deleted file mode 100644
index 521c8d4f8fb..00000000000
--- a/chromium/fuchsia/mojom/test_typemaps.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2019 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.
-
-typemaps = [ "//fuchsia/mojom/example.typemap" ]
diff --git a/chromium/fuchsia/release_channel.gni b/chromium/fuchsia/release_channel.gni
deleted file mode 100644
index 1bab7421f82..00000000000
--- a/chromium/fuchsia/release_channel.gni
+++ /dev/null
@@ -1,15 +0,0 @@
-# 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.
-
-declare_args() {
- # Specifies the name of the release channel for specific packages
- # (web_engine, web_runner, cast_runner) when buildng on a release bot.
- fuchsia_release_channel = ""
-}
-
-if (fuchsia_release_channel != "") {
- release_channel_suffix = "-${fuchsia_release_channel}"
-} else {
- release_channel_suffix = ""
-}
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>();