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

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: add comments 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()));
haraken 2016/10/11 03:45:47 Or you can use V8TestingScope, which will provide
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(DefinitelyProcessingUserGesture);
184
185 BaseAudioContext* audioContext =
186 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
187 recordAutoplayStatus(audioContext);
188
189 histogramTester.expectBucketCount(kCrossOriginMetric,
190 AutoplayStatus::AutoplayStatusSucceeded, 1);
191 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
192 }
193
194 TEST_F(BaseAudioContextTest, AutoplayMetrics_CallResumeGesture) {
195 HistogramTester histogramTester;
196 createChildFrame();
197 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
198
199 ScriptState::Scope scope(getScriptStateFrom(childDocument()));
200
201 BaseAudioContext* audioContext =
202 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
203
204 UserGestureIndicator userGestureScope(DefinitelyProcessingUserGesture);
205
206 audioContext->resumeContext(getScriptStateFrom(childDocument()));
207 rejectPendingResolvers(audioContext);
208 recordAutoplayStatus(audioContext);
209
210 histogramTester.expectBucketCount(kCrossOriginMetric,
211 AutoplayStatus::AutoplayStatusSucceeded, 1);
212 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
213 }
214
215 TEST_F(BaseAudioContextTest, AutoplayMetrics_NodeStartNoGesture) {
216 HistogramTester histogramTester;
217 createChildFrame();
218 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
219
220 BaseAudioContext* audioContext =
221 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
222 audioContext->maybeRecordStartAttempt();
223 recordAutoplayStatus(audioContext);
224
225 histogramTester.expectBucketCount(kCrossOriginMetric,
226 AutoplayStatus::AutoplayStatusFailed, 1);
227 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
228 }
229
230 TEST_F(BaseAudioContextTest, AutoplayMetrics_NodeStartGesture) {
231 HistogramTester histogramTester;
232 createChildFrame();
233 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
234
235 BaseAudioContext* audioContext =
236 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
237
238 UserGestureIndicator userGestureScope(DefinitelyProcessingUserGesture);
239 audioContext->maybeRecordStartAttempt();
240 recordAutoplayStatus(audioContext);
241
242 histogramTester.expectBucketCount(
243 kCrossOriginMetric, AutoplayStatus::AutoplayStatusFailedWithStart, 1);
244 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
245 }
246
247 TEST_F(BaseAudioContextTest, AutoplayMetrics_NodeStartNoGestureThenSuccess) {
248 HistogramTester histogramTester;
249 createChildFrame();
250 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
251
252 ScriptState::Scope scope(getScriptStateFrom(childDocument()));
253
254 BaseAudioContext* audioContext =
255 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
256 audioContext->maybeRecordStartAttempt();
257
258 UserGestureIndicator userGestureScope(DefinitelyProcessingUserGesture);
259 audioContext->resumeContext(getScriptStateFrom(childDocument()));
260 rejectPendingResolvers(audioContext);
261 recordAutoplayStatus(audioContext);
262
263 histogramTester.expectBucketCount(kCrossOriginMetric,
264 AutoplayStatus::AutoplayStatusSucceeded, 1);
265 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
266 }
267
268 TEST_F(BaseAudioContextTest, AutoplayMetrics_NodeStartGestureThenSucces) {
269 HistogramTester histogramTester;
270 createChildFrame();
271 childDocument().settings()->setMediaPlaybackRequiresUserGesture(true);
272
273 ScriptState::Scope scope(getScriptStateFrom(childDocument()));
274
275 BaseAudioContext* audioContext =
276 BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION);
277
278 UserGestureIndicator userGestureScope(DefinitelyProcessingUserGesture);
279 audioContext->maybeRecordStartAttempt();
280 audioContext->resumeContext(getScriptStateFrom(childDocument()));
281 rejectPendingResolvers(audioContext);
282 recordAutoplayStatus(audioContext);
283
284 histogramTester.expectBucketCount(kCrossOriginMetric,
285 AutoplayStatus::AutoplayStatusSucceeded, 1);
286 histogramTester.expectTotalCount(kCrossOriginMetric, 1);
287 }
288
289 } // 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