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

Side by Side Diff: content/browser/renderer_host/media/render_frame_audio_output_service_unittest.cc

Issue 2319493002: Add mojo interface for audio rendering. (Closed)
Patch Set: ++docs Created 3 years, 10 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 "content/browser/renderer_host/media/render_frame_audio_output_service. h"
6
7 #include <cmath>
8 #include <limits>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/memory/shared_memory.h"
13 #include "base/memory/shared_memory_handle.h"
14 #include "base/run_loop.h"
15 #include "base/sync_socket.h"
16 #include "content/browser/audio_manager_thread.h"
17 #include "content/browser/renderer_host/media/audio_output_service_context_impl. h"
18 #include "content/browser/renderer_host/media/media_stream_manager.h"
19 #include "content/common/media/audio_output.mojom.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/test/mock_render_process_host.h"
22 #include "content/public/test/test_browser_context.h"
23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "media/audio/audio_output_controller.h"
25 #include "media/audio/fake_audio_log_factory.h"
26 #include "media/audio/fake_audio_manager.h"
27 #include "media/base/audio_parameters.h"
28 #include "media/base/media_switches.h"
29 #include "mojo/public/cpp/bindings/binding.h"
30 #include "mojo/public/cpp/system/platform_handle.h"
31 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33
34 namespace content {
35
36 namespace {
37
38 using testing::_;
39 using testing::StrictMock;
40 using testing::Return;
41 using testing::Test;
42 using AudioOutputService = mojom::RendererAudioOutputService;
43 using AudioOutputServicePtr = mojo::InterfacePtr<AudioOutputService>;
44 using AudioOutputServiceRequest = mojo::InterfaceRequest<AudioOutputService>;
45 using AudioOutput = mojom::AudioOutput;
46 using AudioOutputPtr = mojo::InterfacePtr<AudioOutput>;
47 using AudioOutputRequest = mojo::InterfaceRequest<AudioOutput>;
48
49 const int kRenderProcessId = 42;
50 const int kRenderFrameId = 24;
51 const char kSecurityOrigin[] = "http://localhost";
52 const char kSalt[] = "salt";
53 const media::AudioParameters params(
54 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
55 media::CHANNEL_LAYOUT_MONO,
56 44100 /*sample frequency*/,
57 16 /*bits per sample*/,
58 441 /*10 ms buffers*/);
59
60 class MockAudioOutputDelegate : public AudioOutputDelegate {
61 MOCK_CONST_METHOD0(GetController,
62 scoped_refptr<media::AudioOutputController>());
63 MOCK_CONST_METHOD0(GetStreamId, int());
64 MOCK_METHOD0(OnPlayStream, void());
65 MOCK_METHOD0(OnPauseStream, void());
66 MOCK_METHOD1(OnSetVolume, void(double));
67 };
68
69 class MockContext : public AudioOutputServiceContext {
70 public:
71 explicit MockContext(bool auth_ok, int render_process_id = kRenderProcessId)
72 : render_process_id_(render_process_id),
73 salt_(kSalt),
74 auth_ok_(auth_ok) {}
75
76 ~MockContext() { EXPECT_EQ(nullptr, delegate_); }
77
78 int GetRenderProcessId() const override { return render_process_id_; }
79
80 void RequestDeviceAuthorization(
81 int render_frame_id,
82 int session_id,
83 const std::string& device_id,
84 const url::Origin& security_origin,
85 AuthorizationCompletedCallback cb) const override {
86 EXPECT_EQ(render_frame_id, kRenderFrameId);
87 EXPECT_EQ(session_id, 0);
88 if (auth_ok_) {
89 base::ThreadTaskRunnerHandle::Get()->PostTask(
90 FROM_HERE,
91 base::Bind(cb, media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
92 false, media::AudioParameters::UnavailableDeviceParams(),
93 "default"));
94 return;
95 }
96 base::ThreadTaskRunnerHandle::Get()->PostTask(
97 FROM_HERE,
98 base::Bind(cb, media::OutputDeviceStatus::
99 OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
100 false, media::AudioParameters::UnavailableDeviceParams(),
101 "default"));
102 }
103
104 const std::string& GetSalt() const override { return salt_; }
105
106 void PrepareDelegateForCreation(
107 std::unique_ptr<AudioOutputDelegate> delegate) {
108 EXPECT_EQ(nullptr, delegate_);
109 delegate_ = std::move(delegate);
110 }
111
112 std::unique_ptr<AudioOutputDelegate> CreateDelegate(
113 const std::string& unique_device_id,
114 int render_frame_id,
115 AudioOutputDelegate::EventHandler* handler,
116 const media::AudioParameters& params) override {
117 EXPECT_NE(nullptr, delegate_);
118 return std::move(delegate_);
119 }
120
121 MOCK_METHOD1(OnServiceFinished,
122 void(mojom::RendererAudioOutputService* service));
123
124 private:
125 int render_process_id_ = kRenderProcessId;
126 const std::string salt_;
127 const bool auth_ok_;
128 std::unique_ptr<AudioOutputDelegate> delegate_;
129 };
130
131 void AuthCallback(media::OutputDeviceStatus* status_out,
132 media::AudioParameters* params_out,
133 std::string* id_out,
134 media::OutputDeviceStatus status,
135 const media::AudioParameters& params,
136 const std::string& id) {
137 *status_out = status;
138 *params_out = params;
139 *id_out = id;
140 }
141
142 } // namespace
143
144 class RenderFrameAudioOutputServiceTest : public Test {
145 public:
146 RenderFrameAudioOutputServiceTest() {}
147
148 ~RenderFrameAudioOutputServiceTest() override {}
149
150 private:
151 TestBrowserThreadBundle thread_bundle_;
152 };
153
154 TEST_F(RenderFrameAudioOutputServiceTest, AuthWithoutStreamRequest) {
155 AudioOutputServicePtr service_ptr;
156 auto service_context_ = base::MakeUnique<MockContext>(true);
157 auto service_ = base::MakeUnique<RenderFrameAudioOutputService>(
158 service_context_.get(), kRenderFrameId, mojo::MakeRequest(&service_ptr));
159
160 media::OutputDeviceStatus status;
161 media::AudioParameters params2;
162 std::string id;
163 service_ptr->RequestDeviceAuthorization(
164 nullptr, /*session_id*/ 0, "default", url::Origin(GURL(kSecurityOrigin)),
165 base::Bind(&AuthCallback, base::Unretained(&status),
166 base::Unretained(&params2), base::Unretained(&id)));
167 base::RunLoop().RunUntilIdle();
168 EXPECT_EQ(status, media::OUTPUT_DEVICE_STATUS_OK);
169 EXPECT_TRUE(id.empty());
170 }
171
172 TEST_F(RenderFrameAudioOutputServiceTest, AuthWithStreamRequest) {
173 AudioOutputServicePtr service_ptr;
174 AudioOutputPtr output_ptr;
175 auto service_context = base::MakeUnique<MockContext>(true);
176 service_context->PrepareDelegateForCreation(
177 base::MakeUnique<MockAudioOutputDelegate>());
178 auto service = base::MakeUnique<RenderFrameAudioOutputService>(
179 service_context.get(), kRenderFrameId, mojo::MakeRequest(&service_ptr));
180
181 media::OutputDeviceStatus status;
182 media::AudioParameters params2;
183 std::string id;
184 service_ptr->RequestDeviceAuthorization(
185 mojo::MakeRequest<AudioOutput>(&output_ptr), /*session_id*/ 0, "default",
186 url::Origin(GURL(kSecurityOrigin)),
187 base::Bind(&AuthCallback, base::Unretained(&status),
188 base::Unretained(&params2), base::Unretained(&id)));
189 base::RunLoop().RunUntilIdle();
190 EXPECT_EQ(status, media::OUTPUT_DEVICE_STATUS_OK);
191 EXPECT_TRUE(id.empty());
192
193 output_ptr->Start(params,
194 base::Bind([](mojo::ScopedSharedBufferHandle handle1,
195 mojo::ScopedHandle handle2) {}));
196 base::RunLoop().RunUntilIdle();
197 output_ptr.reset();
198 }
199
200 TEST_F(RenderFrameAudioOutputServiceTest, AuthWithStreamRequestDenied) {
201 AudioOutputServicePtr service_ptr;
202 AudioOutputPtr output_ptr;
203 auto service_context = base::MakeUnique<MockContext>(false);
204 auto service = base::MakeUnique<RenderFrameAudioOutputService>(
205 service_context.get(), kRenderFrameId, mojo::MakeRequest(&service_ptr));
206
207 media::OutputDeviceStatus status;
208 media::AudioParameters params2;
209 std::string id;
210 service_ptr->RequestDeviceAuthorization(
211 mojo::MakeRequest<AudioOutput>(&output_ptr), /*session_id*/ 0, "default",
212 url::Origin(GURL(kSecurityOrigin)),
213 base::Bind(&AuthCallback, base::Unretained(&status),
214 base::Unretained(&params2), base::Unretained(&id)));
215 base::RunLoop().RunUntilIdle();
216 EXPECT_EQ(status, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED);
217 EXPECT_TRUE(id.empty());
218
219 output_ptr->Start(params,
220 base::Bind([](mojo::ScopedSharedBufferHandle handle1,
221 mojo::ScopedHandle handle2) {}));
222 base::RunLoop().RunUntilIdle();
223 output_ptr.reset();
224 }
225
226 TEST_F(RenderFrameAudioOutputServiceTest, OutOfRangeSessionId_BadMessage) {
227 // This test checks that we get a bad message if session_id is too large
228 // to fit in an integer. This ensures that we don't overflow when casting the
229 // int64_t to an int
230 if (sizeof(int) >= sizeof(int64_t)) {
231 // In this case, any int64_t would fit in an int, and the case we are
232 // checking for is impossible.
233 return;
234 }
235
236 TestBrowserContext browser_context;
237 MockRenderProcessHost rph(&browser_context);
238
239 AudioOutputServicePtr service_ptr;
240 auto service_context = base::MakeUnique<MockContext>(true, rph.GetID());
241 auto service = base::MakeUnique<RenderFrameAudioOutputService>(
242 service_context.get(), kRenderFrameId, mojo::MakeRequest(&service_ptr));
243 EXPECT_CALL(*service_context, OnServiceFinished(service.get()));
244
245 int64_t session_id = std::numeric_limits<int>::max();
246 ++session_id;
247 service_ptr->RequestDeviceAuthorization(
248 nullptr, session_id, "default", url::Origin(GURL(kSecurityOrigin)),
249 base::Bind([](media::OutputDeviceStatus, const media::AudioParameters&,
250 const std::string&) { EXPECT_FALSE(true); }));
251 base::RunLoop().RunUntilIdle();
252 EXPECT_EQ(1, rph.bad_msg_count());
253 }
254
255 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/media/render_frame_audio_output_service.cc ('k') | content/common/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698