diff options
Diffstat (limited to 'chromium/fuchsia/engine')
49 files changed, 1576 insertions, 363 deletions
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", |