blob: 4b99ecc59ba33d23046e9b74a2fd0abce35c4e00 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h"
#include <algorithm>
#include <memory>
#include "ash/frame/frame_view_ash.h"
#include "ash/public/cpp/test/test_new_window_delegate.h"
#include "ash/wm/window_util.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/sharesheet/sharesheet_metrics.h"
#include "chrome/browser/sharesheet/sharesheet_service.h"
#include "chrome/browser/sharesheet/sharesheet_service_factory.h"
#include "chrome/browser/sharesheet/sharesheet_test_util.h"
#include "chrome/browser/sharesheet/sharesheet_types.h"
#include "chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view_delegate.h"
#include "chrome/browser/ui/ash/sharesheet/sharesheet_header_view.h"
#include "chrome/browser/ui/ash/sharesheet/sharesheet_util.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/chrome_ash_test_base.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/components/sharesheet/constants.h"
#include "components/services/app_service/public/cpp/intent.h"
#include "components/services/app_service/public/cpp/intent_util.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/test/clipboard_test_util.h"
#include "ui/base/clipboard/test/test_clipboard.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/mojom/window_show_state.mojom.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/base_event_utils.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/test/test_widget_builder.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_observer.h"
#include "ui/wm/core/transient_window_manager.h"
namespace {
void Click(const views::View* view) {
auto* root_window = view->GetWidget()->GetNativeWindow()->GetRootWindow();
ui::test::EventGenerator event_generator(root_window);
event_generator.MoveMouseTo(view->GetBoundsInScreen().CenterPoint());
event_generator.ClickLeftButton();
}
class TestNewWindowDelegate : public ash::TestNewWindowDelegate {
public:
TestNewWindowDelegate() = default;
TestNewWindowDelegate(const TestNewWindowDelegate&) = delete;
TestNewWindowDelegate& operator=(const TestNewWindowDelegate&) = delete;
~TestNewWindowDelegate() override = default;
void OpenUrl(const GURL& url,
OpenUrlFrom from,
Disposition disposition) override {
url_ = url;
// Window will be deleted by shell upon shutdown.
auto* widget = views::test::TestWidgetBuilder().BuildOwnedByNativeWidget();
ASSERT_TRUE(widget->IsActive());
}
std::optional<GURL> retrieve_url() { return std::move(url_); }
private:
std::optional<GURL> url_;
};
} // namespace
namespace ash {
namespace sharesheet {
class TestWidgetDelegate : public views::WidgetDelegateView {
public:
TestWidgetDelegate() = default;
~TestWidgetDelegate() override = default;
// views::WidgetDelegateView:
bool CanActivate() const override { return true; }
std::unique_ptr<views::FrameView> CreateFrameView(
views::Widget* widget) override {
return std::make_unique<FrameViewAsh>(widget);
}
};
class SharesheetBubbleViewTest : public ChromeAshTestBase,
public views::WidgetObserver {
public:
SharesheetBubbleViewTest() = default;
// ChromeAshTestBase:
void SetUp() override {
new_window_delegate_ = std::make_unique<::TestNewWindowDelegate>();
ChromeAshTestBase::SetUp();
profile_ = std::make_unique<TestingProfile>();
// Set up parent window for sharesheet to anchor to.
auto* widget = new views::Widget();
views::Widget::InitParams params(
views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET);
params.delegate = new TestWidgetDelegate();
params.context = GetContext();
widget->Init(std::move(params));
widget->Show();
widget->GetNativeWindow()->SetProperty(
aura::client::kShowStateKey, ui::mojom::WindowShowState::kFullscreen);
gfx::Size window_size = widget->GetWindowBoundsInScreen().size();
auto* content_view = new views::NativeViewHost();
content_view->SetBounds(0, 0, window_size.width(), window_size.height());
widget->GetContentsView()->AddChildView(content_view);
parent_window_ = widget->GetNativeWindow();
}
void TearDown() override {
if (bubble_delegate_) {
bubble_delegate_->CloseBubble(::sharesheet::SharesheetResult::kCancel);
}
ASSERT_FALSE(sharesheet_bubble_view_);
ChromeAshTestBase::TearDown();
new_window_delegate_.reset();
}
::sharesheet::SharesheetService* GetSharesheetService() {
return ::sharesheet::SharesheetServiceFactory::GetForProfile(
profile_.get());
}
void ShowAndVerifyBubble(
apps::IntentPtr intent,
::sharesheet::LaunchSource source,
std::vector<::sharesheet::ShareActionType> actions = {}) {
auto* sharesheet_service = GetSharesheetService();
sharesheet_service->ShowBubbleForTesting(
parent_window_, std::move(intent), source,
/*delivered_callback=*/base::DoNothing(),
/*close_callback=*/
base::BindOnce(&SharesheetBubbleViewTest::OnClose,
base::Unretained(this)),
actions);
bubble_delegate_ = static_cast<SharesheetBubbleViewDelegate*>(
sharesheet_service->GetUiDelegateForTesting(parent_window_));
EXPECT_NE(bubble_delegate_, nullptr);
sharesheet_bubble_view_ = bubble_delegate_->GetBubbleViewForTesting();
EXPECT_NE(sharesheet_bubble_view_, nullptr);
EXPECT_EQ(sharesheet_bubble_view_->GetID(), SHARESHEET_BUBBLE_VIEW_ID);
sharesheet_bubble_view_->GetWidget()->AddObserver(this);
ASSERT_TRUE(bubble_delegate_->IsBubbleVisible());
sharesheet_widget_ = sharesheet_bubble_view_->GetWidget();
ASSERT_EQ(sharesheet_widget_->GetName(), "SharesheetBubbleView");
ASSERT_TRUE(IsSharesheetVisible());
}
void CloseBubble() {
bubble_delegate_->CloseBubble(::sharesheet::SharesheetResult::kCancel);
ASSERT_FALSE(sharesheet_bubble_view_);
}
void CloseBubbleWithEscKey() {
GetEventGenerator()->PressAndReleaseKey(ui::VKEY_ESCAPE);
ASSERT_FALSE(sharesheet_bubble_view_);
}
bool IsSharesheetVisible() { return sharesheet_widget_->IsVisible(); }
views::Widget* sharesheet_widget() { return sharesheet_widget_; }
void OnClose(views::Widget::ClosedReason reason) {
sharesheet_bubble_view_ = nullptr;
bubble_delegate_ = nullptr;
}
// views::WidgetObserver::
void OnWidgetDestroyed(views::Widget* widget) override {
widget->RemoveObserver(this);
sharesheet_widget_ = nullptr;
}
SharesheetBubbleView* sharesheet_bubble_view() {
return sharesheet_bubble_view_;
}
views::View* header_view() {
return sharesheet_bubble_view_->GetViewByID(HEADER_VIEW_ID);
}
views::View* body_view() {
return sharesheet_bubble_view_->GetViewByID(BODY_VIEW_ID);
}
views::View* footer_view() {
return sharesheet_bubble_view_->GetViewByID(FOOTER_VIEW_ID);
}
Profile* profile() { return profile_.get(); }
private:
gfx::NativeWindow parent_window_;
std::unique_ptr<TestingProfile> profile_;
raw_ptr<SharesheetBubbleViewDelegate> bubble_delegate_;
raw_ptr<SharesheetBubbleView> sharesheet_bubble_view_;
raw_ptr<views::Widget> sharesheet_widget_;
std::unique_ptr<::TestNewWindowDelegate> new_window_delegate_;
};
TEST_F(SharesheetBubbleViewTest, BubbleDoesOpenAndClose) {
ShowAndVerifyBubble(::sharesheet::CreateValidTextIntent(),
::sharesheet::LaunchSource::kUnknown);
CloseBubble();
}
TEST_F(SharesheetBubbleViewTest, RecordLaunchSource) {
base::HistogramTester histograms;
auto source = ::sharesheet::LaunchSource::kFilesAppShareButton;
ShowAndVerifyBubble(::sharesheet::CreateValidTextIntent(), source);
CloseBubble();
histograms.ExpectBucketCount(
::sharesheet::kSharesheetLaunchSourceResultHistogram, source, 1);
source = ::sharesheet::LaunchSource::kArcNearbyShare;
ShowAndVerifyBubble(::sharesheet::CreateValidTextIntent(), source);
CloseBubble();
histograms.ExpectBucketCount(
::sharesheet::kSharesheetLaunchSourceResultHistogram, source, 1);
}
TEST_F(SharesheetBubbleViewTest, ClickCopyToClipboard) {
base::HistogramTester histograms;
// Text intent should only show copy action.
ShowAndVerifyBubble(::sharesheet::CreateValidTextIntent(),
::sharesheet::LaunchSource::kUnknown);
// |targets_view| should only contain the copy to clipboard target.
views::View* targets_view = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::TARGETS_DEFAULT_VIEW_ID);
ASSERT_EQ(targets_view->children().size(), 1u);
// Click on copy target.
Click(targets_view->children()[0]);
// Bubble should close after copy target was pressed.
ASSERT_FALSE(IsSharesheetVisible());
// Copy to clipboard was clicked on.
histograms.ExpectBucketCount(
::sharesheet::kSharesheetUserActionResultHistogram,
::sharesheet::SharesheetMetrics::UserAction::kCopyAction, 1);
// Check text copied correctly.
std::u16string clipboard_text;
ui::Clipboard::GetForCurrentThread()->ReadText(
ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
EXPECT_EQ(::sharesheet::kTestText, base::UTF16ToUTF8(clipboard_text));
}
TEST_F(SharesheetBubbleViewTest, KeyPressCopyToClipboard) {
base::HistogramTester histograms;
// Text intent should only show copy action.
ShowAndVerifyBubble(::sharesheet::CreateValidTextIntent(),
::sharesheet::LaunchSource::kUnknown);
// |targets_view| should only contain the copy to clipboard target.
views::View* targets_view = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::TARGETS_DEFAULT_VIEW_ID);
ASSERT_EQ(targets_view->children().size(), 1u);
GetEventGenerator()->PressAndReleaseKey(ui::VKEY_TAB);
ASSERT_TRUE(targets_view->children()[0]->HasFocus());
GetEventGenerator()->PressAndReleaseKey(ui::VKEY_RETURN);
// Bubble should close after copy target was pressed.
ASSERT_FALSE(IsSharesheetVisible());
// Copy to clipboard was clicked on.
histograms.ExpectBucketCount(
::sharesheet::kSharesheetUserActionResultHistogram,
::sharesheet::SharesheetMetrics::UserAction::kCopyAction, 1);
// Check text copied correctly.
std::u16string clipboard_text;
ui::Clipboard::GetForCurrentThread()->ReadText(
ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
EXPECT_EQ(::sharesheet::kTestText, base::UTF16ToUTF8(clipboard_text));
}
TEST_F(SharesheetBubbleViewTest, ClickAndKeyPressCopyToClipboardTogether) {
base::HistogramTester histograms;
// Text intent should only show copy action.
ShowAndVerifyBubble(::sharesheet::CreateValidTextIntent(),
::sharesheet::LaunchSource::kUnknown);
// |targets_view| should only contain the copy to clipboard target.
views::View* targets_view = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::TARGETS_DEFAULT_VIEW_ID);
ASSERT_EQ(targets_view->children().size(), 1u);
ui::ScopedAnimationDurationScaleMode normal_animation_duration(
ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
GetEventGenerator()->PressAndReleaseKey(ui::VKEY_TAB);
ASSERT_TRUE(targets_view->children()[0]->HasFocus());
// Wait for the widget to get destroyed.
views::test::WidgetDestroyedWaiter widget_observer(sharesheet_widget());
GetEventGenerator()->PressAndReleaseKey(ui::VKEY_RETURN);
// Click on copy target.
Click(targets_view->children()[0]);
// Ensure the widget does close.
widget_observer.Wait();
// Copy to clipboard was clicked on.
histograms.ExpectBucketCount(
::sharesheet::kSharesheetUserActionResultHistogram,
::sharesheet::SharesheetMetrics::UserAction::kCopyAction, 1);
// Check text copied correctly.
std::u16string clipboard_text;
ui::Clipboard::GetForCurrentThread()->ReadText(
ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
EXPECT_EQ(::sharesheet::kTestText, base::UTF16ToUTF8(clipboard_text));
}
TEST_F(SharesheetBubbleViewTest, TextPreview) {
ShowAndVerifyBubble(::sharesheet::CreateValidTextIntent(),
::sharesheet::LaunchSource::kUnknown);
views::View* text_views = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::HEADER_VIEW_TEXT_PREVIEW_ID);
// There should be 3 children, the 'Share' title, the text title and the text.
ASSERT_EQ(text_views->children().size(), 3u);
auto* share_title_text =
static_cast<views::Label*>(text_views->children()[0]);
ASSERT_EQ(share_title_text->GetText(),
l10n_util::GetStringUTF16(IDS_SHARESHEET_TITLE_LABEL));
auto* title_text = static_cast<views::Label*>(text_views->children()[1]);
ASSERT_EQ(title_text->GetText(), u"title");
auto* text = static_cast<views::Label*>(text_views->children()[2]);
ASSERT_EQ(text->GetText(), u"text");
CloseBubble();
}
TEST_F(SharesheetBubbleViewTest, TextPreviewNoTitle) {
auto* text = "text";
ShowAndVerifyBubble(apps_util::MakeShareIntent(text, ""),
::sharesheet::LaunchSource::kUnknown);
views::View* text_views = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::HEADER_VIEW_TEXT_PREVIEW_ID);
// There should be 2 children, the 'Share' title, and the text.
ASSERT_EQ(text_views->children().size(), 2u);
auto* share_title_text =
static_cast<views::Label*>(text_views->children()[0]);
ASSERT_EQ(share_title_text->GetText(),
l10n_util::GetStringUTF16(IDS_SHARESHEET_TITLE_LABEL));
auto* text_label = static_cast<views::Label*>(text_views->children()[1]);
ASSERT_EQ(text_label->GetText(), base::UTF8ToUTF16(text));
CloseBubble();
}
TEST_F(SharesheetBubbleViewTest, TextPreviewOneFile) {
storage::FileSystemURL url = ::sharesheet::FileInDownloads(
profile(), base::FilePath(::sharesheet::kTestTextFile));
ShowAndVerifyBubble(
apps_util::MakeShareIntent({url.ToGURL()}, {::sharesheet::kMimeTypeText}),
::sharesheet::LaunchSource::kUnknown);
views::View* text_views = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::HEADER_VIEW_TEXT_PREVIEW_ID);
// There should be 2 children, the 'Share' title, and the text.
ASSERT_EQ(text_views->children().size(), 2u);
auto* title_text = static_cast<views::Label*>(text_views->children()[1]);
ASSERT_EQ(title_text->GetText(), u"text.txt");
ASSERT_EQ(title_text->GetViewAccessibility().GetCachedName(), u"text.txt");
CloseBubble();
}
TEST_F(SharesheetBubbleViewTest, TextPreviewMultipleFiles) {
storage::FileSystemURL url1 = ::sharesheet::FileInDownloads(
profile(), base::FilePath(::sharesheet::kTestPdfFile));
storage::FileSystemURL url2 = ::sharesheet::FileInDownloads(
profile(), base::FilePath(::sharesheet::kTestTextFile));
ShowAndVerifyBubble(apps_util::MakeShareIntent({url1.ToGURL(), url2.ToGURL()},
{::sharesheet::kMimeTypePdf,
::sharesheet::kMimeTypeText}),
::sharesheet::LaunchSource::kUnknown);
views::View* text_views = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::HEADER_VIEW_TEXT_PREVIEW_ID);
// There should be 2 children, the 'Share' title, and the text.
ASSERT_EQ(text_views->children().size(), 2u);
auto* title_text = static_cast<views::Label*>(text_views->children()[1]);
ASSERT_EQ(title_text->GetText(), u"2 files");
ASSERT_EQ(title_text->GetViewAccessibility().GetCachedName(),
u"2 files file.pdf, text.txt");
CloseBubble();
}
TEST_F(SharesheetBubbleViewTest, URLPreviewAverage) {
auto* kTitleText = "URLTitle";
auto* kURLText = "https://fake-url.com/fake";
ShowAndVerifyBubble(apps_util::MakeShareIntent(kURLText, kTitleText),
::sharesheet::LaunchSource::kUnknown);
views::View* text_views = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::HEADER_VIEW_TEXT_PREVIEW_ID);
// There should be 3 children, the 'Share' title, the URL title, and the URL.
ASSERT_EQ(text_views->children().size(), 3u);
auto* title_text = static_cast<views::Label*>(text_views->children()[1]);
ASSERT_EQ(title_text->GetText(), base::UTF8ToUTF16(kTitleText));
auto* url_text = static_cast<views::Label*>(text_views->children()[2]);
ASSERT_EQ(url_text->GetText(), base::UTF8ToUTF16(kURLText));
CloseBubble();
}
TEST_F(SharesheetBubbleViewTest, URLPreviewLongSubDomain) {
auto* kURLText =
"https://very-very-very-very-very-very-very-very-long-fake-url.com/fake";
ShowAndVerifyBubble(apps_util::MakeShareIntent(kURLText, ""),
::sharesheet::LaunchSource::kUnknown);
views::View* text_views = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::HEADER_VIEW_TEXT_PREVIEW_ID);
// There should be 2 children, the 'Share' title, and the URL.
ASSERT_EQ(text_views->children().size(), 2u);
auto* url_text = static_cast<views::Label*>(text_views->children()[1]);
ASSERT_EQ(url_text->GetText(),
u"very-very-very-very-very-very-very-very-long-fake-…");
ASSERT_EQ(url_text->GetTooltipText(), base::UTF8ToUTF16(kURLText));
CloseBubble();
}
TEST_F(SharesheetBubbleViewTest, URLPreviewLongSubDirectory) {
auto* kURLText =
"https://fake-url.com/very-very-very-very-very-very-very-very-long-fake";
ShowAndVerifyBubble(apps_util::MakeShareIntent(kURLText, ""),
::sharesheet::LaunchSource::kUnknown);
views::View* text_views = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::HEADER_VIEW_TEXT_PREVIEW_ID);
// There should be 2 children, the 'Share' title, and the URL.
ASSERT_EQ(text_views->children().size(), 2u);
auto* url_text = static_cast<views::Label*>(text_views->children()[1]);
ASSERT_EQ(url_text->GetText(),
u"fake-url.com/very-very-very-very-very-very-very-v…");
ASSERT_EQ(url_text->GetTooltipText(), base::UTF8ToUTF16(kURLText));
CloseBubble();
}
TEST_F(SharesheetBubbleViewTest,
URLPreviewLongSecondLevelDomainAndLongSubDirectory) {
auto* kURLText =
"https://very-very-very-very-very-very-very-very-long.fake-url.com/"
"very-very-very-very-very-very-very-very-long-fake";
ShowAndVerifyBubble(apps_util::MakeShareIntent(kURLText, ""),
::sharesheet::LaunchSource::kUnknown);
views::View* text_views = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::HEADER_VIEW_TEXT_PREVIEW_ID);
// There should be 2 children, the 'Share' title, and the URL.
ASSERT_EQ(text_views->children().size(), 2u);
auto* url_text = static_cast<views::Label*>(text_views->children()[1]);
ASSERT_EQ(url_text->GetText(),
u"…fake-url.com/very-very-very-very-very-very-very…");
ASSERT_EQ(url_text->GetTooltipText(), base::UTF8ToUTF16(kURLText));
CloseBubble();
}
TEST_F(SharesheetBubbleViewTest, URLPreviewInternationalCharacters) {
auto* kURLText = "https://xn--p8j9a0d9c9a.xn--q9jyb4c/";
ShowAndVerifyBubble(apps_util::MakeShareIntent(kURLText, ""),
::sharesheet::LaunchSource::kUnknown);
views::View* text_views = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::HEADER_VIEW_TEXT_PREVIEW_ID);
// There should be 2 children, the 'Share' title, and the URL.
ASSERT_EQ(text_views->children().size(), 2u);
auto* url_text = static_cast<views::Label*>(text_views->children()[1]);
ASSERT_EQ(url_text->GetText(), u"https://はじめよう.みんな");
ASSERT_EQ(url_text->GetTooltipText(), u"https://はじめよう.みんな");
CloseBubble();
}
TEST_F(SharesheetBubbleViewTest, URLPreviewEmojis) {
// Text is encoded in IDN.
auto* kURLText = "https://hello.com/\xF0\x9F\x98\x81/";
ShowAndVerifyBubble(apps_util::MakeShareIntent(kURLText, ""),
::sharesheet::LaunchSource::kUnknown);
views::View* text_views = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::HEADER_VIEW_TEXT_PREVIEW_ID);
// There should be 2 children, the 'Share' title, and the URL.
ASSERT_EQ(text_views->children().size(), 2u);
auto* url_text = static_cast<views::Label*>(text_views->children()[1]);
ASSERT_EQ(url_text->GetText(), u"https://hello.com/😁/");
ASSERT_EQ(url_text->GetTooltipText(), u"https://hello.com/😁/");
CloseBubble();
}
TEST_F(SharesheetBubbleViewTest, CloseWithEscKey) {
ShowAndVerifyBubble(::sharesheet::CreateValidTextIntent(),
::sharesheet::LaunchSource::kUnknown);
CloseBubbleWithEscKey();
}
TEST_F(SharesheetBubbleViewTest, CloseMultipleTimes) {
ShowAndVerifyBubble(::sharesheet::CreateValidTextIntent(),
::sharesheet::LaunchSource::kUnknown);
CloseBubbleWithEscKey();
CloseBubbleWithEscKey();
}
TEST_F(SharesheetBubbleViewTest, HoldEscapeKey) {
GetEventGenerator()->PressKey(ui::VKEY_ESCAPE, ui::EF_NONE);
ShowAndVerifyBubble(::sharesheet::CreateValidTextIntent(),
::sharesheet::LaunchSource::kUnknown);
GetEventGenerator()->ReleaseKey(ui::VKEY_ESCAPE, ui::EF_NONE);
CloseBubbleWithEscKey();
}
TEST_F(SharesheetBubbleViewTest, ShareActionShowsUpAsExpected) {
ShowAndVerifyBubble(::sharesheet::CreateValidTextIntent(),
::sharesheet::LaunchSource::kUnknown,
{::sharesheet::kExample});
views::View* share_action_view = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::SHARE_ACTION_VIEW_ID);
ASSERT_FALSE(share_action_view->GetVisible());
// |targets_view| should only contain the copy to clipboard target & our
// example action target.
views::View* targets_view = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::TARGETS_DEFAULT_VIEW_ID);
ASSERT_EQ(targets_view->children().size(), 2u);
// Click on example target.
Click(targets_view->children()[1]);
ASSERT_TRUE(share_action_view->GetVisible());
CloseBubble();
ASSERT_FALSE(IsSharesheetVisible());
}
TEST_F(SharesheetBubbleViewTest, DriveActionShouldNotCrash) {
auto drive_intent = ::sharesheet::CreateDriveIntent();
auto drive_share_url = drive_intent->drive_share_url.value();
ShowAndVerifyBubble(std::move(drive_intent),
::sharesheet::LaunchSource::kUnknown,
{::sharesheet::ShareActionType::kDriveShare});
views::View* share_action_view = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::SHARE_ACTION_VIEW_ID);
ASSERT_FALSE(share_action_view->GetVisible());
// |targets_view| should contain the share with others, copy, and drive share
// target.
views::View* targets_view = sharesheet_bubble_view()->GetViewByID(
SharesheetViewID::TARGETS_DEFAULT_VIEW_ID);
ASSERT_EQ(targets_view->children().size(), 3u);
// The last one is drive share.
Click(targets_view->children()[2]);
EXPECT_FALSE(sharesheet_bubble_view());
// Make sure the drive action was invoked.
auto* delegate = static_cast<::TestNewWindowDelegate*>(
ash::NewWindowDelegate::GetInstance());
auto url = delegate->retrieve_url();
ASSERT_TRUE(url.has_value());
EXPECT_EQ(drive_share_url, *url);
}
TEST_F(SharesheetBubbleViewTest, ReshowHiddenBubble) {
auto* sharesheet_service = GetSharesheetService();
auto app_window = CreateAppWindow();
auto* transient_window_manager =
::wm::TransientWindowManager::GetIfExists(app_window.get());
EXPECT_EQ(0u, transient_window_manager->transient_children().size());
sharesheet_service->AddShareActionForTest(
::sharesheet::ShareActionType::kNearbyShare);
sharesheet_service->ShowNearbyShareBubbleForArc(
app_window.get(), ::sharesheet::CreateValidTextIntent(),
::sharesheet::LaunchSource::kUnknown, base::DoNothing(),
base::DoNothing(), base::DoNothing());
ASSERT_EQ(1u, transient_window_manager->transient_children().size());
auto* bubble_window = transient_window_manager->transient_children()[0].get();
window_util::MinimizeAndHideWithoutAnimation({app_window.get()});
EXPECT_FALSE(app_window->IsVisible());
EXPECT_FALSE(bubble_window->IsVisible());
// Reshowing the bubble shouldn't crash.
sharesheet_service->ShowNearbyShareBubbleForArc(
app_window.get(), ::sharesheet::CreateValidTextIntent(),
::sharesheet::LaunchSource::kUnknown, base::DoNothing(),
base::DoNothing(), base::DoNothing());
EXPECT_TRUE(bubble_window->IsVisible());
}
} // namespace sharesheet
} // namespace ash