Skip to content

Commit 833b84f

Browse files
author
Raymond Toy
committed
Record whether AudioContext was audible for Autoplay UKM
Implements AudioContextManager mojo interface that can be obtained from a frame so that audible playback from WebAudio can be recorded by the browser. Whenever audible playback starts or stops, a message is sent to the browser indicating such. Bug: 855069 Change-Id: Ib236a9506a2a6d9b53e95948eb5519145805a2cb Reviewed-on: https://chromium-review.googlesource.com/1114147 Reviewed-by: Mounir Lamouri <[email protected]> Reviewed-by: Ken Buchanan <[email protected]> Reviewed-by: Kentaro Hara <[email protected]> Reviewed-by: Kinuko Yasuda <[email protected]> Reviewed-by: Nasko Oskov <[email protected]> Reviewed-by: Hongchan Choi <[email protected]> Commit-Queue: Raymond Toy <[email protected]> Cr-Original-Commit-Position: refs/heads/master@{#587867}(cherry picked from commit e413650) Reviewed-on: https://chromium-review.googlesource.com/1207810 Reviewed-by: Raymond Toy <[email protected]> Cr-Commit-Position: refs/branch-heads/3538@{#55} Cr-Branched-From: 79f7c91-refs/heads/master@{#587811}
1 parent 84a07b5 commit 833b84f

22 files changed

+315
-17
lines changed

content/browser/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,8 @@ jumbo_source_set("browser") {
11711171
"media/url_provision_fetcher.h",
11721172
"media/video_decoder_proxy.cc",
11731173
"media/video_decoder_proxy.h",
1174+
"media/webaudio/audio_context_manager_impl.cc",
1175+
"media/webaudio/audio_context_manager_impl.h",
11741176
"memory/memory_condition_observer.cc",
11751177
"memory/memory_condition_observer.h",
11761178
"memory/memory_coordinator_default_policy.cc",

content/browser/frame_host/interstitial_page_impl.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,4 +1090,16 @@ InterstitialPageImpl::GetOrCreateRootBrowserAccessibilityManager() {
10901090
return web_contents_impl->GetOrCreateRootBrowserAccessibilityManager();
10911091
}
10921092

1093+
void InterstitialPageImpl::AudioContextPlaybackStarted(RenderFrameHost* host,
1094+
int context_id) {
1095+
// Interstitial pages should not be playing any sound via WebAudio
1096+
NOTREACHED();
1097+
}
1098+
1099+
void InterstitialPageImpl::AudioContextPlaybackStopped(RenderFrameHost* host,
1100+
int context_id) {
1101+
// Interstitial pages should not be playing any sound via WebAudio.
1102+
NOTREACHED();
1103+
}
1104+
10931105
} // namespace content

content/browser/frame_host/interstitial_page_impl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
138138
bool user_gesture) override;
139139
void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) override;
140140
Visibility GetVisibility() const override;
141+
void AudioContextPlaybackStarted(RenderFrameHost* host,
142+
int context_id) override;
143+
void AudioContextPlaybackStopped(RenderFrameHost* host,
144+
int context_id) override;
141145

142146
// RenderViewHostDelegate implementation:
143147
RenderViewHostDelegateView* GetDelegateView() override;

content/browser/frame_host/render_frame_host_delegate.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,13 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
386386
// Note: This is also exposed by the RenderWidgetHostDelegate.
387387
virtual ukm::SourceId GetUkmSourceIdForLastCommittedSource() const;
388388

389+
// Notify observers if WebAudio AudioContext has started (or stopped) playing
390+
// audible sounds.
391+
virtual void AudioContextPlaybackStarted(RenderFrameHost* host,
392+
int context_id){};
393+
virtual void AudioContextPlaybackStopped(RenderFrameHost* host,
394+
int context_id){};
395+
389396
protected:
390397
virtual ~RenderFrameHostDelegate() {}
391398
};

content/browser/frame_host/render_frame_host_impl.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
#include "content/browser/media/capture/audio_mirroring_manager.h"
6767
#include "content/browser/media/media_interface_proxy.h"
6868
#include "content/browser/media/session/media_session_service_impl.h"
69+
#include "content/browser/media/webaudio/audio_context_manager_impl.h"
6970
#include "content/browser/payments/payment_app_context_impl.h"
7071
#include "content/browser/permissions/permission_controller_impl.h"
7172
#include "content/browser/permissions/permission_service_context.h"
@@ -782,6 +783,14 @@ void RenderFrameHostImpl::DidCommitProvisionalLoadForTesting(
782783
std::move(interface_provider_request));
783784
}
784785

786+
void RenderFrameHostImpl::AudioContextPlaybackStarted(int audio_context_id) {
787+
delegate_->AudioContextPlaybackStarted(this, audio_context_id);
788+
}
789+
790+
void RenderFrameHostImpl::AudioContextPlaybackStopped(int audio_context_id) {
791+
delegate_->AudioContextPlaybackStopped(this, audio_context_id);
792+
}
793+
785794
SiteInstanceImpl* RenderFrameHostImpl::GetSiteInstance() {
786795
return site_instance_.get();
787796
}
@@ -3594,6 +3603,9 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
35943603

35953604
registry_->AddInterface(base::BindRepeating(
35963605
&BackgroundFetchServiceImpl::CreateForFrame, GetProcess(), routing_id_));
3606+
3607+
registry_->AddInterface(base::BindRepeating(&AudioContextManagerImpl::Create,
3608+
base::Unretained(this)));
35973609
}
35983610

35993611
void RenderFrameHostImpl::ResetWaitingState() {

content/browser/frame_host/render_frame_host_impl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
784784
return *registry_;
785785
}
786786

787+
// Called when the WebAudio AudioContext given by |audio_context_id| has
788+
// started (or stopped) playing audible audio.
789+
void AudioContextPlaybackStarted(int audio_context_id);
790+
void AudioContextPlaybackStopped(int audio_context_id);
791+
787792
protected:
788793
friend class RenderFrameHostFactory;
789794

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright 2018 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "content/public/browser/web_contents_observer.h"
6+
#include "content/public/test/browser_test_utils.h"
7+
#include "content/public/test/content_browser_test.h"
8+
#include "content/public/test/content_browser_test_utils.h"
9+
#include "content/shell/browser/shell.h"
10+
11+
namespace content {
12+
13+
namespace {
14+
// Test for audible playback message.
15+
class WaitForAudioContextAudible : WebContentsObserver {
16+
public:
17+
explicit WaitForAudioContextAudible(WebContents* web_contents)
18+
: WebContentsObserver(web_contents) {
19+
run_loop_.Run();
20+
}
21+
22+
void AudioContextPlaybackStarted(const AudioContextId&) final {
23+
// Stop the run loop when we get the message
24+
run_loop_.Quit();
25+
}
26+
27+
private:
28+
base::RunLoop run_loop_;
29+
30+
DISALLOW_COPY_AND_ASSIGN(WaitForAudioContextAudible);
31+
};
32+
33+
// Test for silent playback started (audible playback stopped).
34+
class WaitForAudioContextSilent : WebContentsObserver {
35+
public:
36+
explicit WaitForAudioContextSilent(WebContents* web_contents)
37+
: WebContentsObserver(web_contents) {
38+
run_loop_.Run();
39+
}
40+
41+
void AudioContextPlaybackStopped(const AudioContextId&) final {
42+
// Stop the run loop when we get the message
43+
run_loop_.Quit();
44+
}
45+
46+
private:
47+
base::RunLoop run_loop_;
48+
49+
DISALLOW_COPY_AND_ASSIGN(WaitForAudioContextSilent);
50+
};
51+
52+
} // namespace
53+
54+
class AudioContextManagerTest : public ContentBrowserTest {};
55+
56+
IN_PROC_BROWSER_TEST_F(AudioContextManagerTest, AudioContextPlaybackRecorded) {
57+
NavigateToURL(shell(),
58+
content::GetTestUrl("media/webaudio/", "playback-test.html"));
59+
60+
// Set gain to 1 to start audible audio and verify we got the
61+
// playback started message.
62+
{
63+
ASSERT_TRUE(ExecuteScript(shell()->web_contents(), "gain.gain.value = 1;"));
64+
WaitForAudioContextAudible wait(shell()->web_contents());
65+
}
66+
67+
// Set gain to 0 to stop audible audio and verify we got the
68+
// playback stopped message.
69+
{
70+
ASSERT_TRUE(ExecuteScript(shell()->web_contents(), "gain.gain.value = 0;"));
71+
WaitForAudioContextSilent wait(shell()->web_contents());
72+
}
73+
}
74+
75+
} // namespace content
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2018 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "content/browser/media/webaudio/audio_context_manager_impl.h"
6+
7+
#include "content/browser/frame_host/render_frame_host_impl.h"
8+
#include "content/browser/web_contents/web_contents_impl.h"
9+
#include "content/public/browser/render_frame_host.h"
10+
#include "content/public/browser/web_contents.h"
11+
#include "mojo/public/cpp/bindings/strong_binding.h"
12+
13+
namespace content {
14+
15+
void AudioContextManagerImpl::Create(
16+
RenderFrameHost* render_frame_host,
17+
blink::mojom::AudioContextManagerRequest request) {
18+
mojo::MakeStrongBinding(
19+
std::make_unique<AudioContextManagerImpl>(render_frame_host),
20+
std::move(request));
21+
}
22+
23+
AudioContextManagerImpl::AudioContextManagerImpl(
24+
RenderFrameHost* render_frame_host)
25+
: render_frame_host_impl_(
26+
static_cast<RenderFrameHostImpl*>(render_frame_host)) {
27+
DCHECK(render_frame_host);
28+
}
29+
30+
AudioContextManagerImpl::~AudioContextManagerImpl() = default;
31+
32+
void AudioContextManagerImpl::AudioContextAudiblePlaybackStarted(
33+
int32_t audio_context_id) {
34+
// Notify observers that audible audio started playing from a WebAudio
35+
// AudioContext.
36+
render_frame_host_impl_->AudioContextPlaybackStarted(audio_context_id);
37+
}
38+
39+
void AudioContextManagerImpl::AudioContextAudiblePlaybackStopped(
40+
int32_t audio_context_id) {
41+
// Notify observers that audible audio stopped playing from a WebAudio
42+
// AudioContext.
43+
render_frame_host_impl_->AudioContextPlaybackStopped(audio_context_id);
44+
}
45+
46+
} // namespace content
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2018 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef CONTENT_BROWSER_MEDIA_WEBAUDIO_AUDIO_CONTEXT_MANAGER_IMPL_H_
6+
#define CONTENT_BROWSER_MEDIA_WEBAUDIO_AUDIO_CONTEXT_MANAGER_IMPL_H_
7+
8+
#include "content/common/content_export.h"
9+
#include "mojo/public/cpp/bindings/binding.h"
10+
#include "third_party/blink/public/mojom/webaudio/audio_context_manager.mojom.h"
11+
12+
namespace content {
13+
14+
class RenderFrameHost;
15+
class RenderFrameHostImpl;
16+
17+
// Implements the mojo interface between WebAudio and the browser so that
18+
// WebAudio can report when audible sounds from an AudioContext starts and
19+
// stops.
20+
class CONTENT_EXPORT AudioContextManagerImpl
21+
: public blink::mojom::AudioContextManager {
22+
public:
23+
explicit AudioContextManagerImpl(RenderFrameHost* render_frame_host);
24+
~AudioContextManagerImpl() override;
25+
26+
static void Create(RenderFrameHost* render_frame_host,
27+
blink::mojom::AudioContextManagerRequest request);
28+
29+
// Called when AudioContext starts or stops playing audible audio.
30+
void AudioContextAudiblePlaybackStarted(int32_t audio_context_id) final;
31+
void AudioContextAudiblePlaybackStopped(int32_t audio_context_id) final;
32+
33+
private:
34+
RenderFrameHostImpl* const render_frame_host_impl_;
35+
36+
DISALLOW_COPY_AND_ASSIGN(AudioContextManagerImpl);
37+
};
38+
39+
} // namespace content
40+
41+
#endif // CONTENT_BROWSER_MEDIA_WEBAUDIO_AUDIO_CONTEXT_MANAGER_IMPL_H_

content/browser/web_contents/web_contents_impl.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6517,6 +6517,20 @@ int WebContentsImpl::GetCurrentlyPlayingVideoCount() {
65176517
return currently_playing_video_count_;
65186518
}
65196519

6520+
void WebContentsImpl::AudioContextPlaybackStarted(RenderFrameHost* host,
6521+
int context_id) {
6522+
WebContentsObserver::AudioContextId audio_context_id(host, context_id);
6523+
for (auto& observer : observers_)
6524+
observer.AudioContextPlaybackStarted(audio_context_id);
6525+
}
6526+
6527+
void WebContentsImpl::AudioContextPlaybackStopped(RenderFrameHost* host,
6528+
int context_id) {
6529+
WebContentsObserver::AudioContextId audio_context_id(host, context_id);
6530+
for (auto& observer : observers_)
6531+
observer.AudioContextPlaybackStopped(audio_context_id);
6532+
}
6533+
65206534
void WebContentsImpl::UpdateWebContentsVisibility(Visibility visibility) {
65216535
// Occlusion is disabled when |features::kWebContentsOcclusion| is disabled
65226536
// (for power and speed impact assessment) or when

0 commit comments

Comments
 (0)