Commit 8b18bcfd authored by Will Cassella's avatar Will Cassella Committed by Commit Bot

Add callback to WebMediaPlayerImpl to notify when a redirect occurs

Bug: 1128657
Change-Id: I9548e1f3bfe5693871a56e23c3373f45147e52e0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2422091Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarGuido Urdaneta <guidou@chromium.org>
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809217}
parent 5cf92fe4
...@@ -139,7 +139,7 @@ MultibufferDataSource::MultibufferDataSource( ...@@ -139,7 +139,7 @@ MultibufferDataSource::MultibufferDataSource(
DCHECK(url_data_.get()); DCHECK(url_data_.get());
url_data_->Use(); url_data_->Use();
url_data_->OnRedirect( url_data_->OnRedirect(
base::BindOnce(&MultibufferDataSource::OnRedirect, weak_ptr_)); base::BindOnce(&MultibufferDataSource::OnRedirected, weak_ptr_));
} }
MultibufferDataSource::~MultibufferDataSource() { MultibufferDataSource::~MultibufferDataSource() {
...@@ -213,10 +213,10 @@ void MultibufferDataSource::Initialize(InitializeCB init_cb) { ...@@ -213,10 +213,10 @@ void MultibufferDataSource::Initialize(InitializeCB init_cb) {
} }
} }
void MultibufferDataSource::OnRedirect( void MultibufferDataSource::OnRedirected(
const scoped_refptr<UrlData>& destination) { const scoped_refptr<UrlData>& new_destination) {
if (!destination) { if (!new_destination) {
// A failure occured. // A failure occurred.
failed_ = true; failed_ = true;
if (init_cb_) { if (init_cb_) {
render_task_runner_->PostTask( render_task_runner_->PostTask(
...@@ -229,38 +229,39 @@ void MultibufferDataSource::OnRedirect( ...@@ -229,38 +229,39 @@ void MultibufferDataSource::OnRedirect(
StopLoader(); StopLoader();
return; return;
} }
if (url_data_->url().GetOrigin() != destination->url().GetOrigin()) { if (url_data_->url().GetOrigin() != new_destination->url().GetOrigin()) {
single_origin_ = false; single_origin_ = false;
} }
SetReader(nullptr); SetReader(nullptr);
url_data_ = std::move(destination); url_data_ = std::move(new_destination);
if (url_data_) { url_data_->OnRedirect(
url_data_->OnRedirect( base::BindOnce(&MultibufferDataSource::OnRedirected, weak_ptr_));
base::BindOnce(&MultibufferDataSource::OnRedirect, weak_ptr_));
if (init_cb_) { if (init_cb_) {
CreateResourceLoader(0, kPositionNotSpecified); CreateResourceLoader(0, kPositionNotSpecified);
if (reader_->Available()) { if (reader_->Available()) {
render_task_runner_->PostTask( render_task_runner_->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&MultibufferDataSource::StartCallback, weak_ptr_)); base::BindOnce(&MultibufferDataSource::StartCallback, weak_ptr_));
} else { } else {
reader_->Wait(1, base::BindOnce(&MultibufferDataSource::StartCallback, reader_->Wait(
weak_ptr_)); 1, base::BindOnce(&MultibufferDataSource::StartCallback, weak_ptr_));
} }
} else if (read_op_) { } else if (read_op_) {
CreateResourceLoader(read_op_->position(), kPositionNotSpecified); CreateResourceLoader(read_op_->position(), kPositionNotSpecified);
if (reader_->Available()) { if (reader_->Available()) {
render_task_runner_->PostTask( render_task_runner_->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_)); base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_));
} else { } else {
reader_->Wait( reader_->Wait(
1, base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_)); 1, base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_));
}
} }
} }
if (redirect_cb_)
redirect_cb_.Run();
} }
void MultibufferDataSource::SetPreload(Preload preload) { void MultibufferDataSource::SetPreload(Preload preload) {
...@@ -281,6 +282,10 @@ bool MultibufferDataSource::IsCorsCrossOrigin() const { ...@@ -281,6 +282,10 @@ bool MultibufferDataSource::IsCorsCrossOrigin() const {
return url_data_->is_cors_cross_origin(); return url_data_->is_cors_cross_origin();
} }
void MultibufferDataSource::OnRedirect(RedirectCB callback) {
redirect_cb_ = std::move(callback);
}
bool MultibufferDataSource::HasAccessControl() const { bool MultibufferDataSource::HasAccessControl() const {
return url_data_->has_access_control(); return url_data_->has_access_control();
} }
......
...@@ -39,6 +39,7 @@ class MultiBufferReader; ...@@ -39,6 +39,7 @@ class MultiBufferReader;
class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource { class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
public: public:
using DownloadingCB = base::RepeatingCallback<void(bool)>; using DownloadingCB = base::RepeatingCallback<void(bool)>;
using RedirectCB = base::RepeatingCallback<void()>;
// Used to specify video preload states. They are "hints" to the browser about // Used to specify video preload states. They are "hints" to the browser about
// how aggressively the browser should load and buffer data. // how aggressively the browser should load and buffer data.
...@@ -83,6 +84,9 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource { ...@@ -83,6 +84,9 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
// This must be called after the response arrives. // This must be called after the response arrives.
bool IsCorsCrossOrigin() const; bool IsCorsCrossOrigin() const;
// Provides a callback to be run when the underlying url is redirected.
void OnRedirect(RedirectCB callback);
// Returns true if the response includes an Access-Control-Allow-Origin // Returns true if the response includes an Access-Control-Allow-Origin
// header (that is not "null"). // header (that is not "null").
bool HasAccessControl() const; bool HasAccessControl() const;
...@@ -129,7 +133,7 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource { ...@@ -129,7 +133,7 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
bool cancel_on_defer_for_testing() const { return cancel_on_defer_; } bool cancel_on_defer_for_testing() const { return cancel_on_defer_; }
protected: protected:
void OnRedirect(const scoped_refptr<UrlData>& destination); void OnRedirected(const scoped_refptr<UrlData>& new_destination);
// A factory method to create a BufferedResourceLoader based on the read // A factory method to create a BufferedResourceLoader based on the read
// parameters. // parameters.
...@@ -244,6 +248,9 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource { ...@@ -244,6 +248,9 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
// go between different origins. // go between different origins.
bool single_origin_; bool single_origin_;
// Callback used when a redirect occurs.
RedirectCB redirect_cb_;
// Close the connection when we have enough data. // Close the connection when we have enough data.
bool cancel_on_defer_; bool cancel_on_defer_;
......
...@@ -829,6 +829,8 @@ void WebMediaPlayerImpl::DoLoad(LoadType load_type, ...@@ -829,6 +829,8 @@ void WebMediaPlayerImpl::DoLoad(LoadType load_type,
base::BindRepeating(&WebMediaPlayerImpl::NotifyDownloading, base::BindRepeating(&WebMediaPlayerImpl::NotifyDownloading,
weak_this_)); weak_this_));
data_source_.reset(mb_data_source_); data_source_.reset(mb_data_source_);
mb_data_source_->OnRedirect(base::BindRepeating(
&WebMediaPlayerImpl::OnDataSourceRedirected, weak_this_));
mb_data_source_->SetPreload(preload_); mb_data_source_->SetPreload(preload_);
mb_data_source_->SetIsClientAudioElement(client_->IsAudioElement()); mb_data_source_->SetIsClientAudioElement(client_->IsAudioElement());
mb_data_source_->Initialize( mb_data_source_->Initialize(
...@@ -2694,6 +2696,16 @@ void WebMediaPlayerImpl::DataSourceInitialized(bool success) { ...@@ -2694,6 +2696,16 @@ void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
StartPipeline(); StartPipeline();
} }
void WebMediaPlayerImpl::OnDataSourceRedirected() {
DVLOG(1) << __func__;
DCHECK(main_task_runner_->BelongsToCurrentThread());
DCHECK(mb_data_source_);
if (WouldTaintOrigin()) {
audio_source_provider_->TaintOrigin();
}
}
void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
DVLOG(1) << __func__ << "(" << is_downloading << ")"; DVLOG(1) << __func__ << "(" << is_downloading << ")";
if (!is_downloading && network_state_ == WebMediaPlayer::kNetworkStateLoading) if (!is_downloading && network_state_ == WebMediaPlayer::kNetworkStateLoading)
......
...@@ -383,6 +383,9 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl ...@@ -383,6 +383,9 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
// Called after asynchronous initialization of a data source completed. // Called after asynchronous initialization of a data source completed.
void DataSourceInitialized(bool success); void DataSourceInitialized(bool success);
// Called if the |MultiBufferDataSource| is redirected.
void OnDataSourceRedirected();
// Called when the data source is downloading or paused. // Called when the data source is downloading or paused.
void NotifyDownloading(bool is_downloading); void NotifyDownloading(bool is_downloading);
......
...@@ -81,6 +81,7 @@ class BLINK_PLATFORM_EXPORT WebAudioSourceProviderImpl ...@@ -81,6 +81,7 @@ class BLINK_PLATFORM_EXPORT WebAudioSourceProviderImpl
bool CurrentThreadIsRenderingThread() override; bool CurrentThreadIsRenderingThread() override;
void SwitchOutputDevice(const std::string& device_id, void SwitchOutputDevice(const std::string& device_id,
media::OutputDeviceStatusCB callback) override; media::OutputDeviceStatusCB callback) override;
void TaintOrigin();
// These methods allow a client to get a copy of the rendered audio. // These methods allow a client to get a copy of the rendered audio.
void SetCopyAudioCallback(CopyAudioCB callback); void SetCopyAudioCallback(CopyAudioCB callback);
......
...@@ -102,7 +102,7 @@ class HTMLAudioElementCapturerSourceTest : public testing::Test { ...@@ -102,7 +102,7 @@ class HTMLAudioElementCapturerSourceTest : public testing::Test {
media_stream_component_ = MakeGarbageCollected<MediaStreamComponent>( media_stream_component_ = MakeGarbageCollected<MediaStreamComponent>(
media_stream_source_->Id(), media_stream_source_); media_stream_source_->Id(), media_stream_source_);
// |media_stream_source_| takes wnership of // |media_stream_source_| takes ownership of
// HtmlAudioElementCapturerSource. // HtmlAudioElementCapturerSource.
auto capture_source = std::make_unique<HtmlAudioElementCapturerSource>( auto capture_source = std::make_unique<HtmlAudioElementCapturerSource>(
audio_source_, blink::scheduler::GetSingleThreadTaskRunnerForTesting()); audio_source_, blink::scheduler::GetSingleThreadTaskRunnerForTesting());
...@@ -182,4 +182,36 @@ TEST_F(HTMLAudioElementCapturerSourceTest, ...@@ -182,4 +182,36 @@ TEST_F(HTMLAudioElementCapturerSourceTest,
track()->RemoveSink(&sink); track()->RemoveSink(&sink);
} }
TEST_F(HTMLAudioElementCapturerSourceTest, TaintedPlayerDeliversMutedAudio) {
testing::InSequence s;
base::RunLoop run_loop;
base::OnceClosure quit_closure = run_loop.QuitClosure();
MockMediaStreamAudioSink sink;
track()->AddSink(&sink);
EXPECT_CALL(sink, OnSetFormat(testing::_)).Times(1);
EXPECT_CALL(
sink,
OnData(testing::AllOf(
testing::Property(&media::AudioBus::channels,
kNumChannelsForTest),
testing::Property(&media::AudioBus::frames,
kAudioTrackSamplesPerBuffer),
testing::Property(&media::AudioBus::AreFramesZero, true)),
testing::_))
.Times(1)
.WillOnce([&](const auto&, auto) { std::move(quit_closure).Run(); });
audio_source_->TaintOrigin();
std::unique_ptr<media::AudioBus> bus =
media::AudioBus::Create(kNumChannelsForTest, kAudioTrackSamplesPerBuffer);
InjectAudio(bus.get());
run_loop.Run();
track()->Stop();
track()->RemoveSink(&sink);
}
} // namespace blink } // namespace blink
...@@ -82,6 +82,10 @@ class WebAudioSourceProviderImpl::TeeFilter ...@@ -82,6 +82,10 @@ class WebAudioSourceProviderImpl::TeeFilter
const int num_rendered_frames = renderer_->Render( const int num_rendered_frames = renderer_->Render(
delay, delay_timestamp, prior_frames_skipped, audio_bus); delay, delay_timestamp, prior_frames_skipped, audio_bus);
// Zero out frames after rendering
if (origin_tainted_.IsSet())
audio_bus->Zero();
// Avoid taking the copy lock for the vast majority of cases. // Avoid taking the copy lock for the vast majority of cases.
if (copy_required_) { if (copy_required_) {
base::AutoLock auto_lock(copy_lock_); base::AutoLock auto_lock(copy_lock_);
...@@ -115,11 +119,18 @@ class WebAudioSourceProviderImpl::TeeFilter ...@@ -115,11 +119,18 @@ class WebAudioSourceProviderImpl::TeeFilter
copy_audio_bus_callback_ = std::move(callback); copy_audio_bus_callback_ = std::move(callback);
} }
void TaintOrigin() { origin_tainted_.Set(); }
private: private:
AudioRendererSink::RenderCallback* renderer_ = nullptr; AudioRendererSink::RenderCallback* renderer_ = nullptr;
int channels_ = 0; int channels_ = 0;
int sample_rate_ = 0; int sample_rate_ = 0;
// Indicates whether the audio source is tainted, and output should be muted.
// This can happen if the media element source is a cross-origin source which
// the page is not allowed to access due to CORS restrictions.
base::AtomicFlag origin_tainted_;
// The vast majority of the time we're operating in passthrough mode. So only // The vast majority of the time we're operating in passthrough mode. So only
// acquire a lock to read |copy_audio_bus_callback_| when necessary. // acquire a lock to read |copy_audio_bus_callback_| when necessary.
std::atomic<bool> copy_required_; std::atomic<bool> copy_required_;
...@@ -325,6 +336,10 @@ void WebAudioSourceProviderImpl::SwitchOutputDevice( ...@@ -325,6 +336,10 @@ void WebAudioSourceProviderImpl::SwitchOutputDevice(
sink_->SwitchOutputDevice(device_id, std::move(callback)); sink_->SwitchOutputDevice(device_id, std::move(callback));
} }
void WebAudioSourceProviderImpl::TaintOrigin() {
tee_filter_->TaintOrigin();
}
void WebAudioSourceProviderImpl::SetCopyAudioCallback(CopyAudioCB callback) { void WebAudioSourceProviderImpl::SetCopyAudioCallback(CopyAudioCB callback) {
DCHECK(!callback.is_null()); DCHECK(!callback.is_null());
tee_filter_->SetCopyAudioCallback(std::move(callback)); tee_filter_->SetCopyAudioCallback(std::move(callback));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment