| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.h" |
| |
| #include "base/bind.h" |
| #include "base/run_loop.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/media/webrtc/desktop_media_list_observer.h" |
| #include "chrome/browser/media/webrtc/fake_desktop_media_list.h" |
| #import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h" |
| #import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "testing/gtest_mac.h" |
| |
| using content::DesktopMediaID; |
| |
| @interface DesktopMediaPickerController (ExposedForTesting) |
| - (IKImageBrowserView*)screenBrowser; |
| - (IKImageBrowserView*)windowBrowser; |
| - (NSTableView*)tabBrowser; |
| - (NSSegmentedControl*)sourceTypeControl; |
| - (NSButton*)shareButton; |
| - (NSButton*)audioShareCheckbox; |
| - (NSArray*)screenItems; |
| - (NSArray*)windowItems; |
| - (NSArray*)tabItems; |
| @end |
| |
| @implementation DesktopMediaPickerController (ExposedForTesting) |
| - (IKImageBrowserView*)screenBrowser { |
| return screenBrowser_; |
| } |
| |
| - (IKImageBrowserView*)windowBrowser { |
| return windowBrowser_; |
| } |
| |
| - (NSTableView*)tabBrowser { |
| return tabBrowser_; |
| } |
| |
| - (NSSegmentedControl*)sourceTypeControl { |
| return sourceTypeControl_; |
| } |
| |
| - (NSButton*)shareButton { |
| return shareButton_; |
| } |
| |
| - (NSButton*)cancelButton { |
| return cancelButton_; |
| } |
| |
| - (NSButton*)audioShareCheckbox { |
| return audioShareCheckbox_; |
| } |
| |
| - (NSArray*)screenItems { |
| return screenItems_; |
| } |
| |
| - (NSArray*)windowItems { |
| return windowItems_; |
| } |
| |
| - (NSArray*)tabItems { |
| return tabItems_; |
| } |
| |
| @end |
| |
| class DesktopMediaPickerControllerTest : public CocoaTest { |
| public: |
| DesktopMediaPickerControllerTest() {} |
| |
| void SetUp() override { |
| CocoaTest::SetUp(); |
| |
| std::vector<DesktopMediaID::Type> source_types = { |
| DesktopMediaID::TYPE_SCREEN, DesktopMediaID::TYPE_WINDOW, |
| DesktopMediaID::TYPE_WEB_CONTENTS}; |
| |
| screen_list_ = new FakeDesktopMediaList(DesktopMediaID::TYPE_SCREEN); |
| window_list_ = new FakeDesktopMediaList(DesktopMediaID::TYPE_WINDOW); |
| tab_list_ = new FakeDesktopMediaList(DesktopMediaID::TYPE_WEB_CONTENTS); |
| |
| std::vector<std::unique_ptr<DesktopMediaList>> source_lists; |
| source_lists.push_back(std::unique_ptr<DesktopMediaList>(screen_list_)); |
| source_lists.push_back(std::unique_ptr<DesktopMediaList>(window_list_)); |
| source_lists.push_back(std::unique_ptr<DesktopMediaList>(tab_list_)); |
| |
| DesktopMediaPicker::DoneCallback callback = |
| base::Bind(&DesktopMediaPickerControllerTest::OnResult, |
| base::Unretained(this)); |
| |
| DesktopMediaPicker::Params params; |
| params.app_name = base::ASCIIToUTF16("Screenshare Test"); |
| params.target_name = base::ASCIIToUTF16("https://foo.com"); |
| params.request_audio = true; |
| params.approve_audio_by_default = true; |
| controller_.reset([[DesktopMediaPickerController alloc] |
| initWithSourceLists:std::move(source_lists) |
| callback:callback |
| params:params]); |
| } |
| |
| void TearDown() override { |
| controller_.reset(); |
| CocoaTest::TearDown(); |
| } |
| |
| bool WaitForCallback() { |
| if (!callback_called_) { |
| base::RunLoop().RunUntilIdle(); |
| } |
| return callback_called_; |
| } |
| |
| void ChangeType(DesktopMediaID::Type sourceType) { |
| NSSegmentedControl* control = [controller_ sourceTypeControl]; |
| [control selectSegmentWithTag:sourceType]; |
| // [control selectSegmentWithTag] does not trigger handler, so we need to |
| // trigger it manually. |
| [[control target] performSelector:[control action] withObject:control]; |
| } |
| |
| void AddWindow(int id) { |
| window_list_->AddSourceByFullMediaID( |
| DesktopMediaID(DesktopMediaID::TYPE_WINDOW, id)); |
| } |
| |
| void AddScreen(int id) { |
| screen_list_->AddSourceByFullMediaID( |
| DesktopMediaID(DesktopMediaID::TYPE_SCREEN, id)); |
| } |
| |
| void AddTab(int id) { |
| tab_list_->AddSourceByFullMediaID( |
| DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, id)); |
| } |
| |
| protected: |
| void OnResult(DesktopMediaID source) { |
| EXPECT_FALSE(callback_called_); |
| callback_called_ = true; |
| source_reported_ = source; |
| } |
| |
| content::TestBrowserThreadBundle thread_bundle_; |
| bool callback_called_ = false; |
| DesktopMediaID source_reported_; |
| FakeDesktopMediaList* screen_list_ = nullptr; |
| FakeDesktopMediaList* window_list_ = nullptr; |
| FakeDesktopMediaList* tab_list_ = nullptr; |
| base::scoped_nsobject<DesktopMediaPickerController> controller_; |
| }; |
| |
| TEST_F(DesktopMediaPickerControllerTest, ShowAndDismiss) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_SCREEN); |
| |
| AddScreen(0); |
| AddScreen(1); |
| screen_list_->SetSourceThumbnail(1); |
| |
| NSArray* items = [controller_ screenItems]; |
| EXPECT_EQ(2U, [items count]); |
| EXPECT_NSEQ(@"0", [[items objectAtIndex:0] imageTitle]); |
| EXPECT_EQ(nil, [[items objectAtIndex:0] imageRepresentation]); |
| EXPECT_NSEQ(@"1", [[items objectAtIndex:1] imageTitle]); |
| EXPECT_TRUE([[items objectAtIndex:1] imageRepresentation] != nil); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, CancelIsDefault) { |
| [controller_ showWindow:nil]; |
| EXPECT_EQ([[controller_ window] defaultButtonCell], |
| [[controller_ cancelButton] cell]); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, ClickShareScreen) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_SCREEN); |
| |
| EXPECT_FALSE([[controller_ shareButton] isEnabled]); |
| AddScreen(0); |
| screen_list_->SetSourceThumbnail(0); |
| // Nothing should be selected automatically. |
| EXPECT_FALSE([[controller_ shareButton] isEnabled]); |
| |
| AddScreen(1); |
| screen_list_->SetSourceThumbnail(1); |
| |
| EXPECT_EQ(2U, [[controller_ screenItems] count]); |
| |
| NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:1]; |
| [[controller_ screenBrowser] setSelectionIndexes:index_set |
| byExtendingSelection:NO]; |
| EXPECT_TRUE([[controller_ shareButton] isEnabled]); |
| |
| [[controller_ shareButton] performClick:nil]; |
| EXPECT_TRUE(WaitForCallback()); |
| EXPECT_EQ(screen_list_->GetSource(1).id, source_reported_); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, ClickShareWindow) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_WINDOW); |
| AddWindow(0); |
| window_list_->SetSourceThumbnail(0); |
| AddWindow(1); |
| window_list_->SetSourceThumbnail(1); |
| |
| EXPECT_EQ(2U, [[controller_ windowItems] count]); |
| EXPECT_FALSE([[controller_ shareButton] isEnabled]); |
| |
| NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:1]; |
| [[controller_ windowBrowser] setSelectionIndexes:index_set |
| byExtendingSelection:NO]; |
| EXPECT_TRUE([[controller_ shareButton] isEnabled]); |
| |
| [[controller_ shareButton] performClick:nil]; |
| EXPECT_TRUE(WaitForCallback()); |
| EXPECT_EQ(window_list_->GetSource(1).id, source_reported_); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, ClickShareTab) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS); |
| AddTab(0); |
| tab_list_->SetSourceThumbnail(0); |
| AddTab(1); |
| tab_list_->SetSourceThumbnail(1); |
| |
| EXPECT_EQ(2U, [[controller_ tabItems] count]); |
| EXPECT_FALSE([[controller_ shareButton] isEnabled]); |
| |
| NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:1]; |
| [[controller_ tabBrowser] selectRowIndexes:index_set byExtendingSelection:NO]; |
| EXPECT_TRUE([[controller_ shareButton] isEnabled]); |
| |
| // Disable audio share here, otherwise the |source_reported_| will be |
| // different from original Id, because audio share is by default on. |
| [[controller_ audioShareCheckbox] setState:NSOffState]; |
| [[controller_ shareButton] performClick:nil]; |
| EXPECT_TRUE(WaitForCallback()); |
| EXPECT_EQ(tab_list_->GetSource(1).id, source_reported_); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, ClickCancel) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_WINDOW); |
| |
| AddWindow(0); |
| window_list_->SetSourceThumbnail(0); |
| AddWindow(1); |
| window_list_->SetSourceThumbnail(1); |
| |
| NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:1]; |
| [[controller_ windowBrowser] setSelectionIndexes:index_set |
| byExtendingSelection:NO]; |
| [[controller_ cancelButton] performClick:nil]; |
| EXPECT_TRUE(WaitForCallback()); |
| EXPECT_EQ(DesktopMediaID(), source_reported_); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, CloseWindow) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_SCREEN); |
| |
| AddScreen(0); |
| screen_list_->SetSourceThumbnail(0); |
| AddScreen(1); |
| screen_list_->SetSourceThumbnail(1); |
| |
| [controller_ close]; |
| EXPECT_TRUE(WaitForCallback()); |
| EXPECT_EQ(DesktopMediaID(), source_reported_); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, UpdateThumbnail) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS); |
| |
| AddTab(0); |
| tab_list_->SetSourceThumbnail(0); |
| AddTab(1); |
| tab_list_->SetSourceThumbnail(1); |
| |
| NSArray* items = [controller_ tabItems]; |
| EXPECT_EQ(2U, [items count]); |
| NSUInteger version = [[items objectAtIndex:0] imageVersion]; |
| |
| tab_list_->SetSourceThumbnail(0); |
| EXPECT_NE(version, [[items objectAtIndex:0] imageVersion]); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, UpdateName) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_WINDOW); |
| |
| AddWindow(0); |
| window_list_->SetSourceThumbnail(0); |
| AddWindow(1); |
| window_list_->SetSourceThumbnail(1); |
| |
| NSArray* items = [controller_ windowItems]; |
| EXPECT_EQ(2U, [items count]); |
| NSUInteger version = [[items objectAtIndex:0] imageVersion]; |
| |
| window_list_->SetSourceThumbnail(0); |
| EXPECT_NE(version, [[items objectAtIndex:0] imageVersion]); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, RemoveSource) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_SCREEN); |
| |
| AddScreen(0); |
| AddScreen(1); |
| AddScreen(2); |
| screen_list_->SetSourceName(1, base::ASCIIToUTF16("foo")); |
| |
| NSArray* items = [controller_ screenItems]; |
| EXPECT_EQ(3U, [items count]); |
| EXPECT_NSEQ(@"foo", [[items objectAtIndex:1] imageTitle]); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, MoveSource) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_WINDOW); |
| |
| AddWindow(0); |
| AddWindow(1); |
| window_list_->SetSourceName(1, base::ASCIIToUTF16("foo")); |
| NSArray* items = [controller_ windowItems]; |
| EXPECT_NSEQ(@"foo", [[items objectAtIndex:1] imageTitle]); |
| |
| window_list_->MoveSource(1, 0); |
| EXPECT_NSEQ(@"foo", [[items objectAtIndex:0] imageTitle]); |
| |
| window_list_->MoveSource(0, 1); |
| EXPECT_NSEQ(@"foo", [[items objectAtIndex:1] imageTitle]); |
| } |
| |
| // Make sure the audio share checkbox' state reacts correctly with |
| // the source selection. Namely the checkbox is enabled only for tab |
| // sharing on Mac. |
| TEST_F(DesktopMediaPickerControllerTest, AudioShareCheckboxState) { |
| [controller_ showWindow:nil]; |
| |
| AddScreen(0); |
| AddWindow(1); |
| AddTab(2); |
| |
| NSButton* checkbox = [controller_ audioShareCheckbox]; |
| EXPECT_EQ(YES, [checkbox isHidden]); |
| |
| [checkbox setHidden:NO]; |
| ChangeType(DesktopMediaID::TYPE_WINDOW); |
| EXPECT_EQ(YES, [checkbox isHidden]); |
| |
| [checkbox setHidden:YES]; |
| ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS); |
| EXPECT_EQ(NO, [checkbox isHidden]); |
| |
| [checkbox setHidden:NO]; |
| ChangeType(DesktopMediaID::TYPE_SCREEN); |
| EXPECT_EQ(YES, [checkbox isHidden]); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, TabShareWithAudio) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS); |
| |
| DesktopMediaID origin_id = |
| DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123); |
| DesktopMediaID id_with_audio = origin_id; |
| id_with_audio.audio_share = true; |
| |
| tab_list_->AddSourceByFullMediaID(origin_id); |
| |
| NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:0]; |
| [[controller_ tabBrowser] selectRowIndexes:index_set byExtendingSelection:NO]; |
| EXPECT_TRUE([[controller_ shareButton] isEnabled]); |
| |
| [[controller_ shareButton] performClick:nil]; |
| |
| EXPECT_TRUE(WaitForCallback()); |
| EXPECT_EQ(id_with_audio, source_reported_); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, TabBrowserFocusAlgorithm) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS); |
| AddTab(0); |
| AddTab(1); |
| AddTab(2); |
| AddTab(3); |
| |
| NSArray* items = [controller_ tabItems]; |
| NSTableView* browser = [controller_ tabBrowser]; |
| |
| NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:1]; |
| [browser selectRowIndexes:index_set byExtendingSelection:NO]; |
| |
| // Move source [0, 1, 2, 3]-->[1, 2, 3, 0] |
| tab_list_->MoveSource(0, 3); |
| NSUInteger selected_index = [[browser selectedRowIndexes] firstIndex]; |
| EXPECT_EQ(1, [[items objectAtIndex:selected_index] sourceID].id); |
| |
| // Move source [1, 2, 3, 0]-->[3, 1, 2, 0] |
| tab_list_->MoveSource(2, 0); |
| selected_index = [[browser selectedRowIndexes] firstIndex]; |
| EXPECT_EQ(1, [[items objectAtIndex:selected_index] sourceID].id); |
| |
| // Remove a source [3, 1, 2, 0]-->[1, 2, 0] |
| tab_list_->RemoveSource(0); |
| selected_index = [[browser selectedRowIndexes] firstIndex]; |
| EXPECT_EQ(1, [[items objectAtIndex:selected_index] sourceID].id); |
| |
| // Change source type back and forth, browser should memorize the selection. |
| ChangeType(DesktopMediaID::TYPE_SCREEN); |
| ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS); |
| selected_index = [[browser selectedRowIndexes] firstIndex]; |
| EXPECT_EQ(1, [[items objectAtIndex:selected_index] sourceID].id); |
| } |
| |
| TEST_F(DesktopMediaPickerControllerTest, SingleScreenNoLabel) { |
| [controller_ showWindow:nil]; |
| ChangeType(DesktopMediaID::TYPE_SCREEN); |
| |
| NSArray* items = [controller_ screenItems]; |
| |
| AddScreen(0); |
| screen_list_->SetSourceThumbnail(0); |
| EXPECT_EQ(1U, [items count]); |
| EXPECT_EQ(nil, [[items objectAtIndex:0] imageTitle]); |
| |
| AddScreen(1); |
| screen_list_->SetSourceThumbnail(1); |
| EXPECT_EQ(2U, [items count]); |
| EXPECT_NE(nil, [[items objectAtIndex:0] imageTitle]); |
| EXPECT_NE(nil, [[items objectAtIndex:1] imageTitle]); |
| } |