chromium/chrome/browser/ash/sharesheet/copy_to_clipboard_share_action_unittest.cc

// 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/ash/sharesheet/copy_to_clipboard_share_action.h"

#include "ash/public/cpp/system/toast_data.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/sharesheet/share_action/share_action_cache.h"
#include "chrome/browser/sharesheet/sharesheet_metrics.h"
#include "chrome/browser/sharesheet/sharesheet_test_util.h"
#include "chrome/browser/sharesheet/sharesheet_types.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/chrome_ash_test_base.h"
#include "chrome/test/base/testing_profile.h"
#include "components/services/app_service/public/cpp/intent_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/file_info.h"
#include "ui/base/clipboard/test/clipboard_test_util.h"
#include "ui/base/clipboard/test/test_clipboard.h"
#include "url/gurl.h"

namespace ash::sharesheet {

namespace {

class MockCopyToClipboardShareAction : public CopyToClipboardShareAction {
 public:
  explicit MockCopyToClipboardShareAction(Profile* profile)
      : CopyToClipboardShareAction(profile) {}

  MOCK_METHOD(void, ShowToast, (ash::ToastData toast_data), (override));
};

}  // namespace

class CopyToClipboardShareActionTest : public ChromeAshTestBase {
 public:
  CopyToClipboardShareActionTest() = default;

  // ChromeAshTestBase:
  void SetUp() override {
    ChromeAshTestBase::SetUp();

    profile_ = std::make_unique<TestingProfile>();
    share_action_cache_ =
        std::make_unique<::sharesheet::ShareActionCache>(profile_.get());
  }

  Profile* profile() { return profile_.get(); }
  ::sharesheet::ShareActionCache* share_action_cache() {
    return share_action_cache_.get();
  }

 private:
  std::unique_ptr<TestingProfile> profile_;
  std::unique_ptr<::sharesheet::ShareActionCache> share_action_cache_;
};

TEST_F(CopyToClipboardShareActionTest, CopyToClipboardText) {
  base::HistogramTester histograms;
  auto* copy_action = share_action_cache()->GetActionFromType(
      ::sharesheet::ShareActionType::kCopyToClipboardShare);
  copy_action->LaunchAction(/*controller=*/nullptr, /*root_view=*/nullptr,
                            ::sharesheet::CreateValidTextIntent());
  // 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));
  histograms.ExpectBucketCount(
      ::sharesheet::kSharesheetCopyToClipboardMimeTypeResultHistogram,
      ::sharesheet::SharesheetMetrics::MimeType::kText, 1);
}

TEST_F(CopyToClipboardShareActionTest, CopyToClipboardUrl) {
  base::HistogramTester histograms;
  auto* copy_action = share_action_cache()->GetActionFromType(
      ::sharesheet::ShareActionType::kCopyToClipboardShare);
  copy_action->LaunchAction(/*controller=*/nullptr, /*root_view=*/nullptr,
                            ::sharesheet::CreateValidUrlIntent());
  // Check url copied correctly.
  std::u16string clipboard_url;
  ui::Clipboard::GetForCurrentThread()->ReadText(
      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
      &clipboard_url);
  EXPECT_EQ(::sharesheet::kTestUrl, base::UTF16ToUTF8(clipboard_url));
  histograms.ExpectBucketCount(
      ::sharesheet::kSharesheetCopyToClipboardMimeTypeResultHistogram,
      ::sharesheet::SharesheetMetrics::MimeType::kUrl, 1);
}

TEST_F(CopyToClipboardShareActionTest, CopyToClipboardOneFile) {
  base::HistogramTester histograms;
  auto* copy_action = share_action_cache()->GetActionFromType(
      ::sharesheet::ShareActionType::kCopyToClipboardShare);
  storage::FileSystemURL url = ::sharesheet::FileInDownloads(
      profile(), base::FilePath(::sharesheet::kTestTextFile));
  copy_action->LaunchAction(
      /*controller=*/nullptr, /*root_view=*/nullptr,
      apps_util::MakeShareIntent({url.ToGURL()},
                                 {::sharesheet::kMimeTypeText}));

  // Check filenames copied correctly.
  std::vector<ui::FileInfo> filenames;
  ui::Clipboard::GetForCurrentThread()->ReadFilenames(
      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &filenames);
  EXPECT_EQ(filenames.size(), 1u);
  EXPECT_EQ(url.path(), filenames[0].path);
  histograms.ExpectBucketCount(
      ::sharesheet::kSharesheetCopyToClipboardMimeTypeResultHistogram,
      ::sharesheet::SharesheetMetrics::MimeType::kTextFile, 1);
}

TEST_F(CopyToClipboardShareActionTest, CopyToClipboardMultipleFiles) {
  base::HistogramTester histograms;
  auto* copy_action = share_action_cache()->GetActionFromType(
      ::sharesheet::ShareActionType::kCopyToClipboardShare);
  storage::FileSystemURL url1 = ::sharesheet::FileInDownloads(
      profile(), base::FilePath(::sharesheet::kTestPdfFile));
  storage::FileSystemURL url2 = ::sharesheet::FileInDownloads(
      profile(), base::FilePath(::sharesheet::kTestTextFile));
  copy_action->LaunchAction(
      /*controller=*/nullptr, /*root_view=*/nullptr,
      apps_util::MakeShareIntent(
          {url1.ToGURL(), url2.ToGURL()},
          {::sharesheet::kMimeTypePdf, ::sharesheet::kMimeTypeText}));

  // Check filenames copied correctly.
  std::vector<ui::FileInfo> filenames;
  ui::Clipboard::GetForCurrentThread()->ReadFilenames(
      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &filenames);
  EXPECT_EQ(filenames.size(), 2u);
  EXPECT_EQ(url1.path(), filenames[0].path);
  EXPECT_EQ(url2.path(), filenames[1].path);
  histograms.ExpectBucketCount(
      ::sharesheet::kSharesheetCopyToClipboardMimeTypeResultHistogram,
      ::sharesheet::SharesheetMetrics::MimeType::kTextFile, 1);
  histograms.ExpectBucketCount(
      ::sharesheet::kSharesheetCopyToClipboardMimeTypeResultHistogram,
      ::sharesheet::SharesheetMetrics::MimeType::kPdfFile, 1);
}

TEST_F(CopyToClipboardShareActionTest,
       CopyToClipboardShouldShowActionNonNativeFile) {
  auto* copy_action = share_action_cache()->GetActionFromType(
      ::sharesheet::ShareActionType::kCopyToClipboardShare);
  storage::FileSystemURL url1 = ::sharesheet::FileInNonNativeFileSystemType(
      profile(), base::FilePath(::sharesheet::kTestPdfFile));
  EXPECT_TRUE(copy_action->ShouldShowAction(
      apps_util::MakeShareIntent({url1.ToGURL()}, {::sharesheet::kMimeTypePdf}),
      /* contains_hosted_document= */ false));
}

TEST_F(CopyToClipboardShareActionTest,
       CopyToClipboardShouldShowActionNativeFile) {
  auto* copy_action = share_action_cache()->GetActionFromType(
      ::sharesheet::ShareActionType::kCopyToClipboardShare);
  storage::FileSystemURL url1 = ::sharesheet::FileInDownloads(
      profile(), base::FilePath(::sharesheet::kTestPdfFile));
  EXPECT_TRUE(copy_action->ShouldShowAction(
      apps_util::MakeShareIntent({url1.ToGURL()}, {::sharesheet::kMimeTypePdf}),
      /* contains_hosted_document= */ false));
}

TEST_F(CopyToClipboardShareActionTest,
       CopyToClipboardShouldShowActionHostedDocument) {
  auto* copy_action = share_action_cache()->GetActionFromType(
      ::sharesheet::ShareActionType::kCopyToClipboardShare);
  EXPECT_FALSE(
      copy_action->ShouldShowAction(::sharesheet::CreateDriveIntent(),
                                    /* contains_hosted_document= */ true));
}

TEST_F(CopyToClipboardShareActionTest, CopyTextShowsToast) {
  ::testing::StrictMock<MockCopyToClipboardShareAction> copy_action(profile());
  EXPECT_CALL(copy_action, ShowToast);

  storage::FileSystemURL url = ::sharesheet::FileInDownloads(
      profile(), base::FilePath(::sharesheet::kTestTextFile));
  copy_action.LaunchAction(
      /*controller=*/nullptr, /*root_view=*/nullptr,
      apps_util::MakeShareIntent({url.ToGURL()},
                                 {::sharesheet::kMimeTypeText}));
}

TEST_F(CopyToClipboardShareActionTest, CopyFilesShowsToast) {
  ::testing::StrictMock<MockCopyToClipboardShareAction> copy_action(profile());
  EXPECT_CALL(copy_action, ShowToast);

  storage::FileSystemURL url1 = ::sharesheet::FileInDownloads(
      profile(), base::FilePath(::sharesheet::kTestPdfFile));
  storage::FileSystemURL url2 = ::sharesheet::FileInDownloads(
      profile(), base::FilePath(::sharesheet::kTestTextFile));
  copy_action.LaunchAction(
      /*controller=*/nullptr, /*root_view=*/nullptr,
      apps_util::MakeShareIntent(
          {url1.ToGURL(), url2.ToGURL()},
          {::sharesheet::kMimeTypePdf, ::sharesheet::kMimeTypeText}));
}

TEST_F(CopyToClipboardShareActionTest, CopyToClipboardMultipleImageFiles) {
  base::HistogramTester histograms;
  auto* copy_action = share_action_cache()->GetActionFromType(
      ::sharesheet::ShareActionType::kCopyToClipboardShare);
  storage::FileSystemURL url1 = ::sharesheet::FileInDownloads(
      profile(), base::FilePath("path/to/image1.png"));
  storage::FileSystemURL url2 = ::sharesheet::FileInDownloads(
      profile(), base::FilePath("path/to/image2.jpg"));
  copy_action->LaunchAction(
      /*controller=*/nullptr, /*root_view=*/nullptr,
      apps_util::MakeShareIntent({url1.ToGURL(), url2.ToGURL()},
                                 {"image/png", "image/jpg"}));

  // Check filenames copied correctly.
  std::vector<ui::FileInfo> filenames;
  ui::Clipboard::GetForCurrentThread()->ReadFilenames(
      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &filenames);
  EXPECT_EQ(filenames.size(), 2u);
  EXPECT_EQ(url1.path(), filenames[0].path);
  EXPECT_EQ(url2.path(), filenames[1].path);
  histograms.ExpectBucketCount(
      ::sharesheet::kSharesheetCopyToClipboardMimeTypeResultHistogram,
      ::sharesheet::SharesheetMetrics::MimeType::kImageFile, 1);
}

}  // namespace ash::sharesheet