Commit eb11817e authored by Peter Kasting's avatar Peter Kasting Committed by Commit Bot

Change ButtonPressed overrides to callbacks: .../send_tab_to_self/

This also reworks how the class is tested so only the public API is
tested, and the actual construction/teardown are more like production.

Bug: 772945
Change-Id: I8cd6970d314359296398104484afc7551441808f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2469666
Commit-Queue: Travis Skare <skare@chromium.org>
Reviewed-by: default avatarTravis Skare <skare@chromium.org>
Auto-Submit: Peter Kasting <pkasting@chromium.org>
Cr-Commit-Position: refs/heads/master@{#818678}
parent 24c87c68
...@@ -61,9 +61,14 @@ base::string16 SendTabToSelfBubbleController::GetWindowTitle() const { ...@@ -61,9 +61,14 @@ base::string16 SendTabToSelfBubbleController::GetWindowTitle() const {
return l10n_util::GetStringUTF16(IDS_CONTEXT_MENU_SEND_TAB_TO_SELF); return l10n_util::GetStringUTF16(IDS_CONTEXT_MENU_SEND_TAB_TO_SELF);
} }
const std::vector<TargetDeviceInfo>& std::vector<TargetDeviceInfo> SendTabToSelfBubbleController::GetValidDevices()
SendTabToSelfBubbleController::GetValidDevices() const { const {
return valid_devices_; SendTabToSelfSyncService* const service =
SendTabToSelfSyncServiceFactory::GetForProfile(GetProfile());
SendTabToSelfModel* const model =
service ? service->GetSendTabToSelfModel() : nullptr;
return model ? model->GetTargetDeviceInfoSortedList()
: std::vector<TargetDeviceInfo>();
} }
Profile* SendTabToSelfBubbleController::GetProfile() const { Profile* SendTabToSelfBubbleController::GetProfile() const {
...@@ -111,21 +116,6 @@ SendTabToSelfBubbleController::SendTabToSelfBubbleController( ...@@ -111,21 +116,6 @@ SendTabToSelfBubbleController::SendTabToSelfBubbleController(
content::WebContents* web_contents) content::WebContents* web_contents)
: web_contents_(web_contents) { : web_contents_(web_contents) {
DCHECK(web_contents); DCHECK(web_contents);
FetchDeviceInfo();
}
void SendTabToSelfBubbleController::FetchDeviceInfo() {
valid_devices_.clear();
SendTabToSelfSyncService* service =
SendTabToSelfSyncServiceFactory::GetForProfile(GetProfile());
if (!service) {
return;
}
SendTabToSelfModel* model = service->GetSendTabToSelfModel();
if (!model) {
return;
}
valid_devices_ = model->GetTargetDeviceInfoSortedList();
} }
WEB_CONTENTS_USER_DATA_KEY_IMPL(SendTabToSelfBubbleController) WEB_CONTENTS_USER_DATA_KEY_IMPL(SendTabToSelfBubbleController)
......
...@@ -44,7 +44,7 @@ class SendTabToSelfBubbleController ...@@ -44,7 +44,7 @@ class SendTabToSelfBubbleController
// Returns the title of send tab to self bubble. // Returns the title of send tab to self bubble.
base::string16 GetWindowTitle() const; base::string16 GetWindowTitle() const;
// Returns the valid devices info map. // Returns the valid devices info map.
const std::vector<TargetDeviceInfo>& GetValidDevices() const; virtual std::vector<TargetDeviceInfo> GetValidDevices() const;
// Returns current profile. // Returns current profile.
Profile* GetProfile() const; Profile* GetProfile() const;
...@@ -80,15 +80,10 @@ class SendTabToSelfBubbleController ...@@ -80,15 +80,10 @@ class SendTabToSelfBubbleController
FRIEND_TEST_ALL_PREFIXES(SendTabToSelfBubbleViewImplTest, PopulateScrollView); FRIEND_TEST_ALL_PREFIXES(SendTabToSelfBubbleViewImplTest, PopulateScrollView);
FRIEND_TEST_ALL_PREFIXES(SendTabToSelfBubbleViewImplTest, DevicePressed); FRIEND_TEST_ALL_PREFIXES(SendTabToSelfBubbleViewImplTest, DevicePressed);
// Get information of valid devices.
void FetchDeviceInfo();
// The web_contents associated with this controller. // The web_contents associated with this controller.
content::WebContents* web_contents_; content::WebContents* web_contents_;
// Weak reference. Will be nullptr if no bubble is currently shown. // Weak reference. Will be nullptr if no bubble is currently shown.
SendTabToSelfBubbleView* send_tab_to_self_bubble_view_ = nullptr; SendTabToSelfBubbleView* send_tab_to_self_bubble_view_ = nullptr;
// Valid devices data.
std::vector<TargetDeviceInfo> valid_devices_;
// True if a confirmation message should be shown in the omnibox. // True if a confirmation message should be shown in the omnibox.
bool show_message_ = false; bool show_message_ = false;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/ui/views/hover_button.h" #include "chrome/browser/ui/views/hover_button.h"
#include "chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_view_impl.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "components/send_tab_to_self/target_device_info.h" #include "components/send_tab_to_self/target_device_info.h"
#include "components/sync/protocol/sync.pb.h" #include "components/sync/protocol/sync.pb.h"
...@@ -53,17 +54,18 @@ base::string16 GetLastUpdatedTime(const TargetDeviceInfo& device_info) { ...@@ -53,17 +54,18 @@ base::string16 GetLastUpdatedTime(const TargetDeviceInfo& device_info) {
} // namespace } // namespace
SendTabToSelfBubbleDeviceButton::SendTabToSelfBubbleDeviceButton( SendTabToSelfBubbleDeviceButton::SendTabToSelfBubbleDeviceButton(
views::ButtonListener* button_listener, SendTabToSelfBubbleViewImpl* bubble,
const TargetDeviceInfo& device_info, const TargetDeviceInfo& device_info)
int button_tag) : HoverButton(
: HoverButton(button_listener, base::BindRepeating(&SendTabToSelfBubbleViewImpl::DeviceButtonPressed,
CreateIcon(device_info.device_type), base::Unretained(bubble),
base::UTF8ToUTF16(device_info.device_name), base::Unretained(this)),
GetLastUpdatedTime(device_info)) { CreateIcon(device_info.device_type),
base::UTF8ToUTF16(device_info.device_name),
GetLastUpdatedTime(device_info)) {
device_name_ = device_info.device_name; device_name_ = device_info.device_name;
device_guid_ = device_info.cache_guid; device_guid_ = device_info.cache_guid;
device_type_ = device_info.device_type; device_type_ = device_info.device_type;
set_tag(button_tag);
SetEnabled(true); SetEnabled(true);
} }
......
...@@ -13,15 +13,15 @@ ...@@ -13,15 +13,15 @@
namespace send_tab_to_self { namespace send_tab_to_self {
class SendTabToSelfBubbleViewImpl;
struct TargetDeviceInfo; struct TargetDeviceInfo;
// A button representing a device in share bubble. It is highlighted when // A button representing a device in share bubble. It is highlighted when
// hovered. // hovered.
class SendTabToSelfBubbleDeviceButton : public HoverButton { class SendTabToSelfBubbleDeviceButton : public HoverButton {
public: public:
SendTabToSelfBubbleDeviceButton(views::ButtonListener* button_listener, SendTabToSelfBubbleDeviceButton(SendTabToSelfBubbleViewImpl* bubble,
const TargetDeviceInfo& device_info, const TargetDeviceInfo& device_info);
int button_tag);
~SendTabToSelfBubbleDeviceButton() override; ~SendTabToSelfBubbleDeviceButton() override;
const std::string& device_name() const { return device_name_; } const std::string& device_name() const { return device_name_; }
......
...@@ -40,7 +40,6 @@ SendTabToSelfBubbleViewImpl::SendTabToSelfBubbleViewImpl( ...@@ -40,7 +40,6 @@ SendTabToSelfBubbleViewImpl::SendTabToSelfBubbleViewImpl(
content::WebContents* web_contents, content::WebContents* web_contents,
SendTabToSelfBubbleController* controller) SendTabToSelfBubbleController* controller)
: LocationBarBubbleDelegateView(anchor_view, web_contents), : LocationBarBubbleDelegateView(anchor_view, web_contents),
web_contents_(web_contents),
controller_(controller) { controller_(controller) {
SetButtons(ui::DIALOG_BUTTON_NONE); SetButtons(ui::DIALOG_BUTTON_NONE);
set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric( set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
...@@ -73,11 +72,6 @@ void SendTabToSelfBubbleViewImpl::WindowClosing() { ...@@ -73,11 +72,6 @@ void SendTabToSelfBubbleViewImpl::WindowClosing() {
} }
} }
void SendTabToSelfBubbleViewImpl::ButtonPressed(views::Button* sender,
const ui::Event& event) {
DevicePressed(sender->tag());
}
void SendTabToSelfBubbleViewImpl::OnPaint(gfx::Canvas* canvas) { void SendTabToSelfBubbleViewImpl::OnPaint(gfx::Canvas* canvas) {
views::BubbleDialogDelegateView::OnPaint(canvas); views::BubbleDialogDelegateView::OnPaint(canvas);
} }
...@@ -86,9 +80,19 @@ void SendTabToSelfBubbleViewImpl::Show(DisplayReason reason) { ...@@ -86,9 +80,19 @@ void SendTabToSelfBubbleViewImpl::Show(DisplayReason reason) {
ShowForReason(reason); ShowForReason(reason);
} }
const std::vector<SendTabToSelfBubbleDeviceButton*>& void SendTabToSelfBubbleViewImpl::DeviceButtonPressed(
SendTabToSelfBubbleViewImpl::GetDeviceButtonsForTest() { SendTabToSelfBubbleDeviceButton* device_button) {
return device_buttons_; if (!controller_)
return;
controller_->OnDeviceSelected(device_button->device_name(),
device_button->device_guid());
Hide();
}
const views::View* SendTabToSelfBubbleViewImpl::GetButtonContainerForTesting()
const {
return scroll_view_->contents();
} }
void SendTabToSelfBubbleViewImpl::Init() { void SendTabToSelfBubbleViewImpl::Init() {
...@@ -108,49 +112,29 @@ void SendTabToSelfBubbleViewImpl::Init() { ...@@ -108,49 +112,29 @@ void SendTabToSelfBubbleViewImpl::Init() {
} }
void SendTabToSelfBubbleViewImpl::CreateScrollView() { void SendTabToSelfBubbleViewImpl::CreateScrollView() {
scroll_view_ = new views::ScrollView(); scroll_view_ = AddChildView(std::make_unique<views::ScrollView>());
AddChildView(scroll_view_);
scroll_view_->ClipHeightTo(0, kDeviceButtonHeight * kMaximumButtons); scroll_view_->ClipHeightTo(0, kDeviceButtonHeight * kMaximumButtons);
} }
void SendTabToSelfBubbleViewImpl::PopulateScrollView( void SendTabToSelfBubbleViewImpl::PopulateScrollView(
const std::vector<TargetDeviceInfo>& devices) { const std::vector<TargetDeviceInfo>& devices) {
DCHECK(device_buttons_.empty()); auto* device_list_view =
auto device_list_view = std::make_unique<views::View>(); scroll_view_->SetContents(std::make_unique<views::View>());
device_list_view->SetLayoutManager(std::make_unique<views::BoxLayout>( device_list_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical)); views::BoxLayout::Orientation::kVertical));
int tag = 0;
for (const auto& device : devices) { for (const auto& device : devices) {
auto device_button = std::make_unique<SendTabToSelfBubbleDeviceButton>( device_list_view->AddChildView(
this, device, std::make_unique<SendTabToSelfBubbleDeviceButton>(this, device));
/** button_tag */ tag++);
device_buttons_.push_back(device_button.get());
device_list_view->AddChildView(std::move(device_button));
} }
scroll_view_->SetContents(std::move(device_list_view));
MaybeSizeToContents(); MaybeSizeToContents();
Layout(); Layout();
} }
void SendTabToSelfBubbleViewImpl::DevicePressed(size_t index) {
if (!controller_) {
return;
}
DCHECK_LT(index, device_buttons_.size());
SendTabToSelfBubbleDeviceButton* device_button = device_buttons_[index];
controller_->OnDeviceSelected(device_button->device_name(),
device_button->device_guid());
Hide();
}
void SendTabToSelfBubbleViewImpl::MaybeSizeToContents() { void SendTabToSelfBubbleViewImpl::MaybeSizeToContents() {
// The widget may be null if this is called while the dialog is opening. // The widget may be null if this is called while the dialog is opening.
if (GetWidget()) { if (GetWidget())
SizeToContents(); SizeToContents();
}
} }
} // namespace send_tab_to_self } // namespace send_tab_to_self
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "chrome/browser/ui/media_router/cast_dialog_controller.h" #include "chrome/browser/ui/media_router/cast_dialog_controller.h"
#include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_view.h" #include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
#include "ui/views/controls/button/button.h"
namespace gfx { namespace gfx {
class Canvas; class Canvas;
...@@ -34,7 +33,6 @@ struct TargetDeviceInfo; ...@@ -34,7 +33,6 @@ struct TargetDeviceInfo;
// View component of the send tab to self bubble that allows users to choose // View component of the send tab to self bubble that allows users to choose
// target device to send tab to. // target device to send tab to.
class SendTabToSelfBubbleViewImpl : public SendTabToSelfBubbleView, class SendTabToSelfBubbleViewImpl : public SendTabToSelfBubbleView,
public views::ButtonListener,
public LocationBarBubbleDelegateView { public LocationBarBubbleDelegateView {
public: public:
// Bubble will be anchored to |anchor_view|. // Bubble will be anchored to |anchor_view|.
...@@ -52,24 +50,17 @@ class SendTabToSelfBubbleViewImpl : public SendTabToSelfBubbleView, ...@@ -52,24 +50,17 @@ class SendTabToSelfBubbleViewImpl : public SendTabToSelfBubbleView,
base::string16 GetWindowTitle() const override; base::string16 GetWindowTitle() const override;
void WindowClosing() override; void WindowClosing() override;
// views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// LocationBarBubbleDelegateView: // LocationBarBubbleDelegateView:
void OnPaint(gfx::Canvas* canvas) override; void OnPaint(gfx::Canvas* canvas) override;
// Shows the bubble view. // Shows the bubble view.
void Show(DisplayReason reason); void Show(DisplayReason reason);
// Called by tests. void DeviceButtonPressed(SendTabToSelfBubbleDeviceButton* device_button);
const std::vector<SendTabToSelfBubbleDeviceButton*>&
GetDeviceButtonsForTest();
private: const views::View* GetButtonContainerForTesting() const;
friend class SendTabToSelfBubbleViewImplTest;
FRIEND_TEST_ALL_PREFIXES(SendTabToSelfBubbleViewImplTest, PopulateScrollView);
FRIEND_TEST_ALL_PREFIXES(SendTabToSelfBubbleViewImplTest, DevicePressed);
private:
// views::BubbleDialogDelegateView: // views::BubbleDialogDelegateView:
void Init() override; void Init() override;
...@@ -79,22 +70,15 @@ class SendTabToSelfBubbleViewImpl : public SendTabToSelfBubbleView, ...@@ -79,22 +70,15 @@ class SendTabToSelfBubbleViewImpl : public SendTabToSelfBubbleView,
// Populates the scroll view containing valid devices. // Populates the scroll view containing valid devices.
void PopulateScrollView(const std::vector<TargetDeviceInfo>& devices); void PopulateScrollView(const std::vector<TargetDeviceInfo>& devices);
// Handles the action when a target device has been pressed.
void DevicePressed(size_t index);
// Resizes and potentially moves the bubble to fit the content's preferred // Resizes and potentially moves the bubble to fit the content's preferred
// size. // size.
void MaybeSizeToContents(); void MaybeSizeToContents();
content::WebContents* web_contents_; // Weak reference.
SendTabToSelfBubbleController* controller_; // Weak reference. SendTabToSelfBubbleController* controller_; // Weak reference.
// Title shown at the top of the bubble. // Title shown at the top of the bubble.
base::string16 bubble_title_; base::string16 bubble_title_;
// Contains references to device buttons in the order they appear.
std::vector<SendTabToSelfBubbleDeviceButton*> device_buttons_;
// ScrollView containing the list of device buttons. // ScrollView containing the list of device buttons.
views::ScrollView* scroll_view_ = nullptr; views::ScrollView* scroll_view_ = nullptr;
......
...@@ -25,27 +25,24 @@ class SendTabToSelfBubbleControllerMock : public SendTabToSelfBubbleController { ...@@ -25,27 +25,24 @@ class SendTabToSelfBubbleControllerMock : public SendTabToSelfBubbleController {
SendTabToSelfBubbleControllerMock() = default; SendTabToSelfBubbleControllerMock() = default;
~SendTabToSelfBubbleControllerMock() override = default; ~SendTabToSelfBubbleControllerMock() override = default;
std::vector<TargetDeviceInfo> GetValidDevices() const override {
base::SimpleTestClock clock;
return {{"Device_1", "Device_1", "device_guid_1",
sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
clock.Now() - base::TimeDelta::FromDays(0)},
{"Device_2", "Device_2", "device_guid_2",
sync_pb::SyncEnums_DeviceType_TYPE_WIN,
clock.Now() - base::TimeDelta::FromDays(1)},
{"Device_3", "Device_3", "device_guid_3",
sync_pb::SyncEnums_DeviceType_TYPE_PHONE,
clock.Now() - base::TimeDelta::FromDays(5)}};
}
MOCK_METHOD2(OnDeviceSelected, MOCK_METHOD2(OnDeviceSelected,
void(const std::string& target_device_name, void(const std::string& target_device_name,
const std::string& target_device_guid)); const std::string& target_device_guid));
}; };
class SendTabToSelfBubbleViewImplMock : public SendTabToSelfBubbleViewImpl {
public:
SendTabToSelfBubbleViewImplMock(views::View* anchor_view,
content::WebContents* web_contents,
SendTabToSelfBubbleController* controller)
: SendTabToSelfBubbleViewImpl(anchor_view,
web_contents,
controller) {}
~SendTabToSelfBubbleViewImplMock() override = default;
// The delegate cannot find widget since it is created from a null profile.
// This method will be called inside DevicePressed(). Unit tests will
// chrash without mocking.
MOCK_METHOD0(CloseBubble, void());
};
} // namespace } // namespace
class SendTabToSelfBubbleViewImplTest : public ChromeViewsTestBase { class SendTabToSelfBubbleViewImplTest : public ChromeViewsTestBase {
...@@ -58,54 +55,34 @@ class SendTabToSelfBubbleViewImplTest : public ChromeViewsTestBase { ...@@ -58,54 +55,34 @@ class SendTabToSelfBubbleViewImplTest : public ChromeViewsTestBase {
profile_ = std::make_unique<TestingProfile>(); profile_ = std::make_unique<TestingProfile>();
controller_ = std::make_unique<SendTabToSelfBubbleControllerMock>(); controller_ = std::make_unique<SendTabToSelfBubbleControllerMock>();
bubble_ = std::make_unique<SendTabToSelfBubbleViewImplMock>( bubble_ = new SendTabToSelfBubbleViewImpl(anchor_widget_->GetContentsView(),
anchor_widget_->GetContentsView(), nullptr, controller_.get()); nullptr, controller_.get());
views::BubbleDialogDelegateView::CreateBubble(bubble_);
} }
void TearDown() override { void TearDown() override {
bubble_->GetWidget()->CloseNow();
anchor_widget_.reset(); anchor_widget_.reset();
ChromeViewsTestBase::TearDown(); ChromeViewsTestBase::TearDown();
} }
const std::vector<TargetDeviceInfo> SetUpDeviceList() {
base::SimpleTestClock clock;
std::vector<TargetDeviceInfo> list;
TargetDeviceInfo valid_device_1(
"Device_1", "Device_1", "device_guid_1",
sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
/*last_updated_timestamp=*/clock.Now() - base::TimeDelta::FromDays(0));
TargetDeviceInfo valid_device_2(
"Device_2", "Device_2", "device_guid_2",
sync_pb::SyncEnums_DeviceType_TYPE_WIN,
/*last_updated_timestamp=*/clock.Now() - base::TimeDelta::FromDays(1));
TargetDeviceInfo valid_device_3(
"Device_3", "Device_3", "device_guid_3",
sync_pb::SyncEnums_DeviceType_TYPE_PHONE,
/*last_updated_timestamp=*/clock.Now() - base::TimeDelta::FromDays(5));
list.push_back(valid_device_1);
list.push_back(valid_device_2);
list.push_back(valid_device_3);
return list;
}
std::unique_ptr<TestingProfile> profile_; std::unique_ptr<TestingProfile> profile_;
std::unique_ptr<views::Widget> anchor_widget_; std::unique_ptr<views::Widget> anchor_widget_;
std::unique_ptr<SendTabToSelfBubbleControllerMock> controller_; std::unique_ptr<SendTabToSelfBubbleControllerMock> controller_;
std::unique_ptr<SendTabToSelfBubbleViewImpl> bubble_; SendTabToSelfBubbleViewImpl* bubble_;
}; };
TEST_F(SendTabToSelfBubbleViewImplTest, PopulateScrollView) { TEST_F(SendTabToSelfBubbleViewImplTest, Init) {
bubble_->CreateScrollView(); EXPECT_EQ(3U, bubble_->GetButtonContainerForTesting()->children().size());
bubble_->PopulateScrollView(SetUpDeviceList());
EXPECT_EQ(3UL, bubble_->GetDeviceButtonsForTest().size());
} }
TEST_F(SendTabToSelfBubbleViewImplTest, DevicePressed) { TEST_F(SendTabToSelfBubbleViewImplTest, ButtonPressed) {
bubble_->Init();
bubble_->PopulateScrollView(SetUpDeviceList());
EXPECT_CALL(*controller_.get(), EXPECT_CALL(*controller_.get(),
OnDeviceSelected("Device_3", "device_guid_3")); OnDeviceSelected("Device_3", "device_guid_3"));
bubble_->DevicePressed(2); const views::View* button_container = bubble_->GetButtonContainerForTesting();
ASSERT_EQ(3U, button_container->children().size());
bubble_->DeviceButtonPressed(static_cast<SendTabToSelfBubbleDeviceButton*>(
button_container->children()[2]));
} }
} // namespace send_tab_to_self } // namespace send_tab_to_self
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment