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.
5 #include "chrome/browser/media/desktop_media_picker_model.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/synchronization/lock.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 "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
14 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
15 #include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
22 class MockObserver : public DesktopMediaPickerModel::Observer {
24 MOCK_METHOD1(OnSourceAdded, void(int index));
25 MOCK_METHOD1(OnSourceRemoved, void(int index));
26 MOCK_METHOD1(OnSourceNameChanged, void(int index));
27 MOCK_METHOD1(OnSourceThumbnailChanged, void(int index));
30 class FakeScreenCapturer : public webrtc::ScreenCapturer {
32 FakeScreenCapturer() {}
33 virtual ~FakeScreenCapturer() {}
35 // webrtc::ScreenCapturer implementation.
36 virtual void Start(Callback* callback) OVERRIDE {
40 virtual void Capture(const webrtc::DesktopRegion& region) OVERRIDE {
42 webrtc::DesktopFrame* frame =
43 new webrtc::BasicDesktopFrame(webrtc::DesktopSize(10, 10));
44 memset(frame->data(), 0, frame->stride() * frame->size().height());
45 callback_->OnCaptureCompleted(frame);
48 virtual void SetMouseShapeObserver(
49 MouseShapeObserver* mouse_shape_observer) OVERRIDE {
56 DISALLOW_COPY_AND_ASSIGN(FakeScreenCapturer);
59 class FakeWindowCapturer : public webrtc::WindowCapturer {
64 virtual ~FakeWindowCapturer() {}
66 void SetWindowList(const WindowList& list) {
67 base::AutoLock lock(window_list_lock_);
71 // Sets |value| thats going to be used to memset() content of the frames
72 // generated for |window_id|. By default generated frames are set to zeros.
73 void SetNextFrameValue(WindowId window_id, int8_t value) {
74 base::AutoLock lock(frame_values_lock_);
75 frame_values_[window_id] = value;
78 // webrtc::WindowCapturer implementation.
79 virtual void Start(Callback* callback) OVERRIDE {
83 virtual void Capture(const webrtc::DesktopRegion& region) OVERRIDE {
86 base::AutoLock lock(frame_values_lock_);
88 std::map<WindowId, int8_t>::iterator it =
89 frame_values_.find(selected_window_id_);
90 int8_t value = (it != frame_values_.end()) ? it->second : 0;
91 webrtc::DesktopFrame* frame =
92 new webrtc::BasicDesktopFrame(webrtc::DesktopSize(10, 10));
93 memset(frame->data(), value, frame->stride() * frame->size().height());
94 callback_->OnCaptureCompleted(frame);
97 virtual bool GetWindowList(WindowList* windows) OVERRIDE {
98 base::AutoLock lock(window_list_lock_);
99 *windows = window_list_;
103 virtual bool SelectWindow(WindowId id) OVERRIDE {
104 selected_window_id_ = id;
110 WindowList window_list_;
111 base::Lock window_list_lock_;
113 WindowId selected_window_id_;
115 // Frames to be captured per window.
116 std::map<WindowId, int8_t> frame_values_;
117 base::Lock frame_values_lock_;
119 DISALLOW_COPY_AND_ASSIGN(FakeWindowCapturer);
122 class DesktopMediaPickerModelTest : public testing::Test {
124 DesktopMediaPickerModelTest()
125 : window_capturer_(NULL),
126 ui_thread_(content::BrowserThread::UI,
130 void CreateWithDefaultCapturers() {
131 window_capturer_ = new FakeWindowCapturer();
132 model_.reset(new DesktopMediaPickerModelImpl(
133 scoped_ptr<webrtc::ScreenCapturer>(new FakeScreenCapturer()),
134 scoped_ptr<webrtc::WindowCapturer>(window_capturer_)));
136 // Set update period to reduce the time it takes to run tests.
137 model_->SetUpdatePeriod(base::TimeDelta::FromMilliseconds(0));
141 // Must be listed before |model_|, so it's destroyed last.
142 MockObserver observer_;
144 // Owned by |model_|;
145 FakeWindowCapturer* window_capturer_;
147 scoped_ptr<DesktopMediaPickerModelImpl> model_;
149 base::MessageLoop message_loop_;
150 content::TestBrowserThread ui_thread_;
152 DISALLOW_COPY_AND_ASSIGN(DesktopMediaPickerModelTest);
155 ACTION_P2(CheckListSize, model, expected_list_size) {
156 EXPECT_EQ(expected_list_size, model->source_count());
159 ACTION_P(QuitMessageLoop, message_loop) {
160 message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
163 TEST_F(DesktopMediaPickerModelTest, InitialSourceList) {
164 CreateWithDefaultCapturers();
166 webrtc::WindowCapturer::WindowList list;
167 webrtc::WindowCapturer::Window window;
169 window.title = "Test window";
170 list.push_back(window);
171 window_capturer_->SetWindowList(list);
174 testing::InSequence dummy;
175 EXPECT_CALL(observer_, OnSourceAdded(0))
176 .WillOnce(CheckListSize(model_.get(), 1));
177 EXPECT_CALL(observer_, OnSourceAdded(1))
178 .WillOnce(CheckListSize(model_.get(), 2));
179 EXPECT_CALL(observer_, OnSourceThumbnailChanged(0));
180 EXPECT_CALL(observer_, OnSourceThumbnailChanged(1))
181 .WillOnce(QuitMessageLoop(&message_loop_));
183 model_->StartUpdating(&observer_);
187 EXPECT_EQ(model_->source(0).id.type, content::DesktopMediaID::TYPE_SCREEN);
188 EXPECT_EQ(model_->source(0).id.id, 0);
189 EXPECT_EQ(model_->source(1).id.type, content::DesktopMediaID::TYPE_WINDOW);
190 EXPECT_EQ(model_->source(1).id.id, 0);
191 EXPECT_EQ(model_->source(1).name, UTF8ToUTF16(window.title));
194 // Verifies that the window specified with SetViewDialogWindowId() is filtered
196 TEST_F(DesktopMediaPickerModelTest, Filtering) {
197 CreateWithDefaultCapturers();
199 webrtc::WindowCapturer::WindowList list;
200 webrtc::WindowCapturer::Window window;
203 window.title = "Test window";
204 list.push_back(window);
207 list.push_back(window);
209 window_capturer_->SetWindowList(list);
212 testing::InSequence dummy;
213 EXPECT_CALL(observer_, OnSourceAdded(0))
214 .WillOnce(CheckListSize(model_.get(), 1));
215 EXPECT_CALL(observer_, OnSourceAdded(1))
216 .WillOnce(CheckListSize(model_.get(), 2));
217 EXPECT_CALL(observer_, OnSourceThumbnailChanged(0));
218 EXPECT_CALL(observer_, OnSourceThumbnailChanged(1))
219 .WillOnce(QuitMessageLoop(&message_loop_));
222 model_->SetViewDialogWindowId(0);
224 model_->StartUpdating(&observer_);
227 EXPECT_EQ(model_->source(0).id.type, content::DesktopMediaID::TYPE_SCREEN);
228 EXPECT_EQ(model_->source(0).id.id, 0);
229 EXPECT_EQ(model_->source(1).id.type, content::DesktopMediaID::TYPE_WINDOW);
230 EXPECT_EQ(model_->source(1).id.id, 1);
231 EXPECT_EQ(model_->source(1).name, UTF8ToUTF16(window.title));
234 TEST_F(DesktopMediaPickerModelTest, WindowsOnly) {
235 window_capturer_ = new FakeWindowCapturer();
236 model_.reset(new DesktopMediaPickerModelImpl(
237 scoped_ptr<webrtc::ScreenCapturer>(),
238 scoped_ptr<webrtc::WindowCapturer>(window_capturer_)));
240 webrtc::WindowCapturer::WindowList list;
241 webrtc::WindowCapturer::Window window;
243 window.title = "Test window";
244 list.push_back(window);
245 window_capturer_->SetWindowList(list);
248 testing::InSequence dummy;
249 EXPECT_CALL(observer_, OnSourceAdded(0))
250 .WillOnce(CheckListSize(model_.get(), 1));
251 EXPECT_CALL(observer_, OnSourceThumbnailChanged(0))
252 .WillOnce(QuitMessageLoop(&message_loop_));
254 model_->StartUpdating(&observer_);
258 EXPECT_EQ(model_->source(0).id.type, content::DesktopMediaID::TYPE_WINDOW);
261 TEST_F(DesktopMediaPickerModelTest, ScreenOnly) {
262 model_.reset(new DesktopMediaPickerModelImpl(
263 scoped_ptr<webrtc::ScreenCapturer>(new FakeScreenCapturer),
264 scoped_ptr<webrtc::WindowCapturer>()));
267 testing::InSequence dummy;
268 EXPECT_CALL(observer_, OnSourceAdded(0))
269 .WillOnce(CheckListSize(model_.get(), 1));
270 EXPECT_CALL(observer_, OnSourceThumbnailChanged(0))
271 .WillOnce(QuitMessageLoop(&message_loop_));
273 model_->StartUpdating(&observer_);
277 EXPECT_EQ(model_->source(0).id.type, content::DesktopMediaID::TYPE_SCREEN);
280 TEST_F(DesktopMediaPickerModelTest, AddWindow) {
281 CreateWithDefaultCapturers();
283 webrtc::WindowCapturer::WindowList list;
284 webrtc::WindowCapturer::Window window;
286 window.title = "Test window 1";
287 list.push_back(window);
288 window_capturer_->SetWindowList(list);
291 testing::InSequence dummy;
292 EXPECT_CALL(observer_, OnSourceAdded(0))
293 .WillOnce(CheckListSize(model_.get(), 1));
294 EXPECT_CALL(observer_, OnSourceAdded(1))
295 .WillOnce(CheckListSize(model_.get(), 2));
296 EXPECT_CALL(observer_, OnSourceThumbnailChanged(0));
297 EXPECT_CALL(observer_, OnSourceThumbnailChanged(1))
298 .WillOnce(QuitMessageLoop(&message_loop_));
300 model_->StartUpdating(&observer_);
304 testing::Mock::VerifyAndClearExpectations(&observer_);
306 EXPECT_CALL(observer_, OnSourceAdded(1))
307 .WillOnce(DoAll(CheckListSize(model_.get(), 3),
308 QuitMessageLoop(&message_loop_)));
311 window.title = "Test window 0";
312 list.push_back(window);
313 window_capturer_->SetWindowList(list);
317 EXPECT_EQ(model_->source(1).id.type, content::DesktopMediaID::TYPE_WINDOW);
318 EXPECT_EQ(model_->source(1).id.id, 0);
321 TEST_F(DesktopMediaPickerModelTest, RemoveWindow) {
322 CreateWithDefaultCapturers();
324 webrtc::WindowCapturer::WindowList list;
325 webrtc::WindowCapturer::Window window;
327 window.title = "Test window 0";
328 list.push_back(window);
330 window.title = "Test window 1";
331 list.push_back(window);
332 window_capturer_->SetWindowList(list);
335 testing::InSequence dummy;
336 EXPECT_CALL(observer_, OnSourceAdded(0))
337 .WillOnce(CheckListSize(model_.get(), 1));
338 EXPECT_CALL(observer_, OnSourceAdded(1))
339 .WillOnce(CheckListSize(model_.get(), 2));
340 EXPECT_CALL(observer_, OnSourceAdded(2))
341 .WillOnce(CheckListSize(model_.get(), 3));
342 EXPECT_CALL(observer_, OnSourceThumbnailChanged(0));
343 EXPECT_CALL(observer_, OnSourceThumbnailChanged(1));
344 EXPECT_CALL(observer_, OnSourceThumbnailChanged(2))
345 .WillOnce(QuitMessageLoop(&message_loop_));
347 model_->StartUpdating(&observer_);
351 testing::Mock::VerifyAndClearExpectations(&observer_);
353 EXPECT_CALL(observer_, OnSourceRemoved(1))
354 .WillOnce(DoAll(CheckListSize(model_.get(), 2),
355 QuitMessageLoop(&message_loop_)));
357 list.erase(list.begin());
358 window_capturer_->SetWindowList(list);
363 TEST_F(DesktopMediaPickerModelTest, UpdateTitle) {
364 CreateWithDefaultCapturers();
366 webrtc::WindowCapturer::WindowList list;
367 webrtc::WindowCapturer::Window window;
369 window.title = "Test window";
370 list.push_back(window);
371 window_capturer_->SetWindowList(list);
374 testing::InSequence dummy;
375 EXPECT_CALL(observer_, OnSourceAdded(0))
376 .WillOnce(CheckListSize(model_.get(), 1));
377 EXPECT_CALL(observer_, OnSourceAdded(1))
378 .WillOnce(CheckListSize(model_.get(), 2));
379 EXPECT_CALL(observer_, OnSourceThumbnailChanged(0));
380 EXPECT_CALL(observer_, OnSourceThumbnailChanged(1))
381 .WillOnce(QuitMessageLoop(&message_loop_));
383 model_->StartUpdating(&observer_);
387 testing::Mock::VerifyAndClearExpectations(&observer_);
389 EXPECT_CALL(observer_, OnSourceNameChanged(1))
390 .WillOnce(QuitMessageLoop(&message_loop_));
392 const std::string kTestTitle = "New Title";
394 list[0].title = kTestTitle;
395 window_capturer_->SetWindowList(list);
399 EXPECT_EQ(model_->source(1).name, base::UTF8ToUTF16(kTestTitle));
402 TEST_F(DesktopMediaPickerModelTest, UpdateThumbnail) {
403 CreateWithDefaultCapturers();
405 webrtc::WindowCapturer::WindowList list;
406 webrtc::WindowCapturer::Window window;
408 window.title = "Test window 1";
409 list.push_back(window);
411 window.title = "Test window 2";
412 list.push_back(window);
413 window_capturer_->SetWindowList(list);
416 testing::InSequence dummy;
417 EXPECT_CALL(observer_, OnSourceAdded(0))
418 .WillOnce(CheckListSize(model_.get(), 1));
419 EXPECT_CALL(observer_, OnSourceAdded(1))
420 .WillOnce(CheckListSize(model_.get(), 2));
421 EXPECT_CALL(observer_, OnSourceAdded(2))
422 .WillOnce(CheckListSize(model_.get(), 3));
423 EXPECT_CALL(observer_, OnSourceThumbnailChanged(0));
424 EXPECT_CALL(observer_, OnSourceThumbnailChanged(1));
425 EXPECT_CALL(observer_, OnSourceThumbnailChanged(2))
426 .WillOnce(QuitMessageLoop(&message_loop_));
428 model_->StartUpdating(&observer_);
432 testing::Mock::VerifyAndClearExpectations(&observer_);
434 EXPECT_CALL(observer_, OnSourceThumbnailChanged(1))
435 .WillOnce(QuitMessageLoop(&message_loop_));
437 // Update frame for the window and verify that we get notification about it.
438 window_capturer_->SetNextFrameValue(0, 1);