Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp

Issue 2404743002: Web Audio: record autoplay status when an AudioContext is destroyed. (Closed)
Patch Set: move recording Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "modules/webaudio/BaseAudioContext.h"
6
7 #include "core/dom/Document.h"
8 #include "core/frame/FrameOwner.h"
9 #include "core/frame/FrameView.h"
10 #include "core/frame/Settings.h"
11 #include "core/loader/DocumentLoader.h"
12 #include "core/loader/EmptyClients.h"
13 #include "core/testing/DummyPageHolder.h"
14 #include "platform/UserGestureIndicator.h"
15 #include "platform/testing/HistogramTester.h"
16 #include "platform/testing/TestingPlatformSupport.h"
17 #include "public/platform/WebAudioDevice.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace blink {
21
22 namespace {
23
24 const char* const kCrossOriginMetric = "WebAudio.Autoplay.CrossOrigin";
25
26 class MockCrossOriginFrameLoaderClient final : public EmptyFrameLoaderClient {
27 public:
28 static MockCrossOriginFrameLoaderClient* create(Frame* parent) {
29 return new MockCrossOriginFrameLoaderClient(parent);
30 }
31
32 DEFINE_INLINE_VIRTUAL_TRACE() {
33 visitor->trace(m_parent);
34 EmptyFrameLoaderClient::trace(visitor);
35 }
36
37 Frame* parent() const override { return m_parent.get(); }
38 Frame* top() const override { return m_parent.get(); }
39
40 private:
41 explicit MockCrossOriginFrameLoaderClient(Frame* parent) : m_parent(parent) {}
42
43 Member<Frame> m_parent;
44 };
45
46 class MockWebAudioDevice : public WebAudioDevice {
47 public:
48 explicit MockWebAudioDevice(double sampleRate) : m_sampleRate(sampleRate) {}
49 ~MockWebAudioDevice() override = default;
50
51 void start() override {}
52 void stop() override {}
53 double sampleRate() override { return m_sampleRate; }
54
55 private:
56 double m_sampleRate;
57 };
58
59 class BaseAudioContextTestPlatform : public TestingPlatformSupport {
60 public:
61 WebAudioDevice* createAudioDevice(size_t bufferSize,
62 unsigned numberOfInputChannels,
63 unsigned numberOfChannels,
64 double sampleRate,
65 WebAudioDevice::RenderCallback*,
66 const WebString& deviceId,
67 const WebSecurityOrigin&) override {
68 return new MockWebAudioDevice(sampleRate);
69 }
70
71 double audioHardwareSampleRate() override { return 44100; }
72 };
73
74 } // anonymous namespace
75
76 class BaseAudioContextTest : public ::testing::Test {
77 protected:
78 using AutoplayStatus = BaseAudioContext::AutoplayStatus;
79
80 void SetUp() override {
81 m_dummyPageHolder = DummyPageHolder::create();
82 m_dummyFrameOwner = DummyFrameOwner::create();
83 document().updateSecurityOrigin(
84 SecurityOrigin::create("https", "example.com", 80));
85 }
86
87 void TearDown() override {
88 if (m_childFrame) {
89 m_childDocumentLoader->detachFromFrame();
90 m_childDocumentLoader.clear();
91 m_childFrame->detach(FrameDetachType::Remove);
92 }
93 }
94
95 void createChildFrame() {
96 m_childFrame = LocalFrame::create(
97 MockCrossOriginFrameLoaderClient::create(document().frame()),
98 document().frame()->host(), m_dummyFrameOwner.get());
99 m_childFrame->setView(
100 FrameView::create(m_childFrame.get(), IntSize(500, 500)));
101 m_childFrame->init();
102 m_childDocumentLoader = DocumentLoader::create(
103 m_childFrame.get(), ResourceRequest("https://www.example.com"),
104 SubstituteData());
105
106 childDocument().updateSecurityOrigin(
107 SecurityOrigin::create("https", "cross-origin.com", 80));
108 }
109
110 Document& document() { return m_dummyPageHolder->document(); }
111
112 Document& childDocument() { return *m_childFrame->document(); }
113
114 ScriptState* getScriptStateFrom(const Document& document) {
115 return ScriptState::forMainWorld(document.frame());
116 }
117
118 void rejectPendingResolvers(BaseAudioContext* audioContext) {
119 audioContext->rejectPendingResolvers();
120 }
121
122 void recordAutoplayStatus(BaseAudioContext* audioContext) {
123 audioContext->recordAutoplayStatus();
124 }
125
126 private:
127 std::unique_ptr<DummyPageHolder> m_dummyPageHolder;
128 Persistent<DummyFrameOwner> m_dummyFrameOwner;
129
130 Persistent<LocalFrame> m_childFrame;
131 Persistent<DocumentLoader> m_childDocumentLoader;
132
133 BaseAudioContextTestPlatform m_testPlatform;
134 };
135
136 TEST_F(BaseAudioContextTest, AutoplayMetrics_NoRestriction) {
137 HistogramTester histogramTester;
138
139 BaseAudioContext* audioContext =
140 BaseAudioContext::create(document(), ASSERT_NO_EXCEPTION);
141 recordAutoplayStatus(audioContext);
142
143 histogramTester.expectTotalCount(kCrossOriginMetric, 0);
144 }
145
146 TEST_F(BaseAudioContextTest, AutoplayMetrics_CreateNoGesture) {
147 HistogramTester histogramTester;
148 createChildFrame();
149 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
150
151 BaseAudioContext* audioContext =
152 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
153 recordAutoplayStatus(audioContext);
154
155 histogramTester.expectBucketCount(kCrossOriginMetric,
156 AutoplayStatus::AutoplayStatusFailed, 1);
157 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
158 }
159
160 TEST_F(BaseAudioContextTest, AutoplayMetrics_CallResumeNoGesture) {
161 HistogramTester histogramTester;
162 createChildFrame();
163 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
164
165 ScriptState::Scope scope(getScriptStateFrom(childDocument()));
166
167 BaseAudioContext* audioContext =
168 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
169 audioContext->resumeContext(getScriptStateFrom(childDocument()));
170 rejectPendingResolvers(audioContext);
171 recordAutoplayStatus(audioContext);
172
173 histogramTester.expectBucketCount(kCrossOriginMetric,
174 AutoplayStatus::AutoplayStatusFailed, 1);
175 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
176 }
177
178 TEST_F(BaseAudioContextTest, AutoplayMetrics_CreateGesture) {
179 HistogramTester histogramTester;
180 createChildFrame();
181 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
182
183 UserGestureIndicator userGestureScope(
184 UserGestureToken::create(UserGestureToken::NewGesture));
185
186 BaseAudioContext* audioContext =
187 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
188 recordAutoplayStatus(audioContext);
189
190 histogramTester.expectBucketCount(kCrossOriginMetric,
191 AutoplayStatus::AutoplayStatusSucceeded, 1);
192 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
193 }
194
195 TEST_F(BaseAudioContextTest, AutoplayMetrics_CallResumeGesture) {
196 HistogramTester histogramTester;
197 createChildFrame();
198 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
199
200 ScriptState::Scope scope(getScriptStateFrom(childDocument()));
201
202 BaseAudioContext* audioContext =
203 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
204
205 UserGestureIndicator userGestureScope(
206 UserGestureToken::create(UserGestureToken::NewGesture));
207
208 audioContext->resumeContext(getScriptStateFrom(childDocument()));
209 rejectPendingResolvers(audioContext);
210 recordAutoplayStatus(audioContext);
211
212 histogramTester.expectBucketCount(kCrossOriginMetric,
213 AutoplayStatus::AutoplayStatusSucceeded, 1);
214 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
215 }
216
217 TEST_F(BaseAudioContextTest, AutoplayMetrics_NodeStartNoGesture) {
218 HistogramTester histogramTester;
219 createChildFrame();
220 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
221
222 BaseAudioContext* audioContext =
223 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
224 audioContext->maybeRecordStartAttempt();
225 recordAutoplayStatus(audioContext);
226
227 histogramTester.expectBucketCount(kCrossOriginMetric,
228 AutoplayStatus::AutoplayStatusFailed, 1);
229 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
230 }
231
232 TEST_F(BaseAudioContextTest, AutoplayMetrics_NodeStartGesture) {
233 HistogramTester histogramTester;
234 createChildFrame();
235 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
236
237 BaseAudioContext* audioContext =
238 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
239
240 UserGestureIndicator userGestureScope(
241 UserGestureToken::create(UserGestureToken::NewGesture));
242 audioContext->maybeRecordStartAttempt();
243 recordAutoplayStatus(audioContext);
244
245 histogramTester.expectBucketCount(
246 kCrossOriginMetric, AutoplayStatus::AutoplayStatusFailedWithStart, 1);
247 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
248 }
249
250 TEST_F(BaseAudioContextTest, AutoplayMetrics_NodeStartNoGestureThenSuccess) {
251 HistogramTester histogramTester;
252 createChildFrame();
253 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
254
255 ScriptState::Scope scope(getScriptStateFrom(childDocument()));
256
257 BaseAudioContext* audioContext =
258 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
259 audioContext->maybeRecordStartAttempt();
260
261 UserGestureIndicator userGestureScope(
262 UserGestureToken::create(UserGestureToken::NewGesture));
263 audioContext->resumeContext(getScriptStateFrom(childDocument()));
264 rejectPendingResolvers(audioContext);
265 recordAutoplayStatus(audioContext);
266
267 histogramTester.expectBucketCount(kCrossOriginMetric,
268 AutoplayStatus::AutoplayStatusSucceeded, 1);
269 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
270 }
271
272 TEST_F(BaseAudioContextTest, AutoplayMetrics_NodeStartGestureThenSucces) {
273 HistogramTester histogramTester;
274 createChildFrame();
275 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
276
277 ScriptState::Scope scope(getScriptStateFrom(childDocument()));
278
279 BaseAudioContext* audioContext =
280 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
281
282 UserGestureIndicator userGestureScope(
283 UserGestureToken::create(UserGestureToken::NewGesture));
284 audioContext->maybeRecordStartAttempt();
285 audioContext->resumeContext(getScriptStateFrom(childDocument()));
286 rejectPendingResolvers(audioContext);
287 recordAutoplayStatus(audioContext);
288
289 histogramTester.expectBucketCount(kCrossOriginMetric,
290 AutoplayStatus::AutoplayStatusSucceeded, 1);
291 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
292 }
293
294 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698