1 // Copyright 2013 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/media_stream_ui_proxy.h" 6 7 #include "base/message_loop/message_loop.h" 8 #include "content/browser/renderer_host/render_view_host_delegate.h" 9 #include "content/public/common/renderer_preferences.h" 10 #include "content/public/test/test_browser_thread.h" 11 #include "testing/gmock/include/gmock/gmock.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "ui/gfx/rect.h" 14 15 using testing::_; 16 using testing::SaveArg; 17 18 namespace content { 19 namespace { 20 21 class MockRenderViewHostDelegate : public RenderViewHostDelegate { 22 public: 23 MOCK_METHOD2(RequestMediaAccessPermission, 24 void(const MediaStreamRequest& request, 25 const MediaResponseCallback& callback)); 26 27 // Stubs for pure virtual methods we don't care about. 28 virtual gfx::Rect GetRootWindowResizerRect() const OVERRIDE { 29 NOTREACHED(); 30 return gfx::Rect(); 31 } 32 virtual RendererPreferences GetRendererPrefs( 33 BrowserContext* browser_context) const OVERRIDE { 34 NOTREACHED(); 35 return RendererPreferences(); 36 } 37 }; 38 39 class MockResponseCallback { 40 public: 41 MOCK_METHOD1(OnAccessRequestResponse, 42 void(const MediaStreamDevices& devices)); 43 }; 44 45 class MockMediaStreamUI : public MediaStreamUI { 46 public: 47 MOCK_METHOD1(OnStarted, void(const base::Closure& stop)); 48 }; 49 50 class MockStopStreamHandler { 51 public: 52 MOCK_METHOD0(OnStop, void()); 53 }; 54 55 56 } // namespace 57 58 class MediaStreamUIProxyTest : public testing::Test { 59 public: 60 MediaStreamUIProxyTest() 61 : ui_thread_(BrowserThread::UI, &message_loop_), 62 io_thread_(BrowserThread::IO, &message_loop_) { 63 proxy_ = MediaStreamUIProxy::CreateForTests(&delegate_); 64 } 65 66 virtual ~MediaStreamUIProxyTest() { 67 proxy_.reset(); 68 message_loop_.RunUntilIdle(); 69 } 70 71 protected: 72 base::MessageLoop message_loop_; 73 TestBrowserThread ui_thread_; 74 TestBrowserThread io_thread_; 75 76 MockRenderViewHostDelegate delegate_; 77 MockResponseCallback response_callback_; 78 scoped_ptr<MediaStreamUIProxy> proxy_; 79 }; 80 81 MATCHER_P(SameRequest, expected, "") { 82 return 83 expected.render_process_id == arg.render_process_id && 84 expected.render_view_id == arg.render_view_id && 85 expected.tab_capture_device_id == arg.tab_capture_device_id && 86 expected.security_origin == arg.security_origin && 87 expected.request_type == arg.request_type && 88 expected.requested_audio_device_id == arg.requested_audio_device_id && 89 expected.requested_video_device_id == arg.requested_video_device_id && 90 expected.audio_type == arg.audio_type && 91 expected.video_type == arg.video_type; 92 } 93 94 TEST_F(MediaStreamUIProxyTest, Deny) { 95 MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), 96 MEDIA_GENERATE_STREAM, std::string(), 97 std::string(), 98 MEDIA_DEVICE_AUDIO_CAPTURE, 99 MEDIA_DEVICE_VIDEO_CAPTURE); 100 proxy_->RequestAccess( 101 request, base::Bind(&MockResponseCallback::OnAccessRequestResponse, 102 base::Unretained(&response_callback_))); 103 MediaResponseCallback callback; 104 EXPECT_CALL(delegate_, RequestMediaAccessPermission(SameRequest(request), _)) 105 .WillOnce(SaveArg<1>(&callback)); 106 message_loop_.RunUntilIdle(); 107 ASSERT_FALSE(callback.is_null()); 108 109 MediaStreamDevices devices; 110 callback.Run(devices, scoped_ptr<MediaStreamUI>()); 111 112 MediaStreamDevices response; 113 EXPECT_CALL(response_callback_, OnAccessRequestResponse(_)) 114 .WillOnce(SaveArg<0>(&response)); 115 message_loop_.RunUntilIdle(); 116 117 EXPECT_TRUE(response.empty()); 118 } 119 120 TEST_F(MediaStreamUIProxyTest, AcceptAndStart) { 121 MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), 122 MEDIA_GENERATE_STREAM, std::string(), 123 std::string(), 124 MEDIA_DEVICE_AUDIO_CAPTURE, 125 MEDIA_DEVICE_VIDEO_CAPTURE); 126 proxy_->RequestAccess( 127 request, base::Bind(&MockResponseCallback::OnAccessRequestResponse, 128 base::Unretained(&response_callback_))); 129 MediaResponseCallback callback; 130 EXPECT_CALL(delegate_, RequestMediaAccessPermission(SameRequest(request), _)) 131 .WillOnce(SaveArg<1>(&callback)); 132 message_loop_.RunUntilIdle(); 133 ASSERT_FALSE(callback.is_null()); 134 135 MediaStreamDevices devices; 136 devices.push_back( 137 MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, "Mic", "Mic")); 138 scoped_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI()); 139 EXPECT_CALL(*ui, OnStarted(_)); 140 callback.Run(devices, ui.PassAs<MediaStreamUI>()); 141 142 MediaStreamDevices response; 143 EXPECT_CALL(response_callback_, OnAccessRequestResponse(_)) 144 .WillOnce(SaveArg<0>(&response)); 145 message_loop_.RunUntilIdle(); 146 147 EXPECT_FALSE(response.empty()); 148 149 proxy_->OnStarted(base::Closure()); 150 message_loop_.RunUntilIdle(); 151 } 152 153 // Verify that the proxy can be deleted before the request is processed. 154 TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) { 155 MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), 156 MEDIA_GENERATE_STREAM, std::string(), 157 std::string(), 158 MEDIA_DEVICE_AUDIO_CAPTURE, 159 MEDIA_DEVICE_VIDEO_CAPTURE); 160 proxy_->RequestAccess( 161 request, base::Bind(&MockResponseCallback::OnAccessRequestResponse, 162 base::Unretained(&response_callback_))); 163 MediaResponseCallback callback; 164 EXPECT_CALL(delegate_, RequestMediaAccessPermission(SameRequest(request), _)) 165 .WillOnce(SaveArg<1>(&callback)); 166 message_loop_.RunUntilIdle(); 167 ASSERT_FALSE(callback.is_null()); 168 169 proxy_.reset(); 170 171 MediaStreamDevices devices; 172 scoped_ptr<MediaStreamUI> ui; 173 callback.Run(devices, ui.Pass()); 174 } 175 176 TEST_F(MediaStreamUIProxyTest, StopFromUI) { 177 MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), 178 MEDIA_GENERATE_STREAM, std::string(), 179 std::string(), 180 MEDIA_DEVICE_AUDIO_CAPTURE, 181 MEDIA_DEVICE_VIDEO_CAPTURE); 182 proxy_->RequestAccess( 183 request, base::Bind(&MockResponseCallback::OnAccessRequestResponse, 184 base::Unretained(&response_callback_))); 185 MediaResponseCallback callback; 186 EXPECT_CALL(delegate_, RequestMediaAccessPermission(SameRequest(request), _)) 187 .WillOnce(SaveArg<1>(&callback)); 188 message_loop_.RunUntilIdle(); 189 ASSERT_FALSE(callback.is_null()); 190 191 base::Closure stop_callback; 192 193 MediaStreamDevices devices; 194 devices.push_back( 195 MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, "Mic", "Mic")); 196 scoped_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI()); 197 EXPECT_CALL(*ui, OnStarted(_)) 198 .WillOnce(SaveArg<0>(&stop_callback)); 199 callback.Run(devices, ui.PassAs<MediaStreamUI>()); 200 201 MediaStreamDevices response; 202 EXPECT_CALL(response_callback_, OnAccessRequestResponse(_)) 203 .WillOnce(SaveArg<0>(&response)); 204 message_loop_.RunUntilIdle(); 205 206 EXPECT_FALSE(response.empty()); 207 208 MockStopStreamHandler stop_handler; 209 proxy_->OnStarted(base::Bind(&MockStopStreamHandler::OnStop, 210 base::Unretained(&stop_handler))); 211 message_loop_.RunUntilIdle(); 212 213 ASSERT_FALSE(stop_callback.is_null()); 214 EXPECT_CALL(stop_handler, OnStop()); 215 stop_callback.Run(); 216 message_loop_.RunUntilIdle(); 217 } 218 219 } // content 220