chromium/chrome/browser/webshare/chromeos/sharesheet_client_unittest.cc

// Copyright 2020 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/webshare/chromeos/sharesheet_client.h"

#include <string>
#include <vector>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/safe_base_name.h"
#include "base/functional/bind.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sharesheet/sharesheet_types.h"
#include "chrome/browser/webshare/prepare_directory_task.h"
#include "chrome/browser/webshare/store_file_task.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "content/public/browser/site_instance.h"
#include "content/public/test/web_contents_tester.h"
#include "third_party/blink/public/mojom/webshare/webshare.mojom.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/file_manager/path_util.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chrome/common/chrome_paths_lacros.h"
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

namespace webshare {

class SharesheetClientUnitTest : public ChromeRenderViewHostTestHarness {
 public:
  SharesheetClientUnitTest()
      : ChromeRenderViewHostTestHarness(
            base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}

  void SetUp() override {
    ChromeRenderViewHostTestHarness::SetUp();
    StoreFileTask::SkipCopyingForTesting();
    SharesheetClient::SetSharesheetCallbackForTesting(
        base::BindRepeating(&SharesheetClientUnitTest::AcceptShareRequest));
  }

  void SetGuest() {
    Profile* const otr_profile = profile()->GetOffTheRecordProfile(
        Profile::OTRProfileID::CreateUniqueForTesting(),
        /*create_if_needed=*/true);
    EXPECT_TRUE(otr_profile->IsOffTheRecord());
    EXPECT_FALSE(otr_profile->IsIncognitoProfile());
    scoped_refptr<content::SiteInstance> instance =
        content::SiteInstance::Create(otr_profile);
    SetContents(content::WebContentsTester::CreateTestWebContents(
        otr_profile, std::move(instance)));
  }

  void SetIncognito() {
    Profile* const otr_profile =
        profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true);
    EXPECT_TRUE(otr_profile->IsOffTheRecord());
    EXPECT_TRUE(otr_profile->IsIncognitoProfile());
    scoped_refptr<content::SiteInstance> instance =
        content::SiteInstance::Create(otr_profile);
    SetContents(content::WebContentsTester::CreateTestWebContents(
        otr_profile, std::move(instance)));
  }

  static void AcceptShareRequest(
      content::WebContents* web_contents,
      const std::vector<base::FilePath>& file_paths,
      const std::vector<std::string>& content_types,
      const std::vector<uint64_t>& file_sizes,
      const std::string& text,
      const std::string& title,
      sharesheet::DeliveredCallback delivered_callback) {
    std::move(delivered_callback).Run(sharesheet::SharesheetResult::kSuccess);
  }
};

TEST_F(SharesheetClientUnitTest, TestDenyInIncognitoAfterDelay) {
  SetIncognito();
  SharesheetClient sharesheet_client(web_contents());

  const std::string title = "Subject";
  const std::string text = "Message";
  const GURL share_url("https://example.com/");
  std::vector<blink::mojom::SharedFilePtr> files;
  files.push_back(blink::mojom::SharedFilePtr());

  blink::mojom::ShareError error = blink::mojom::ShareError::INTERNAL_ERROR;
  sharesheet_client.Share(
      title, text, share_url, std::move(files),
      base::BindLambdaForTesting(
          [&error](blink::mojom::ShareError in_error) { error = in_error; }));

  // Should be cancelled after 1-2 seconds. So 500ms is not enough.
  task_environment()->FastForwardBy(base::Milliseconds(500));
  EXPECT_EQ(error, blink::mojom::ShareError::INTERNAL_ERROR);

  // But 5*500ms > 2 seconds, so it should now be cancelled.
  for (int n = 0; n < 4; n++)
    task_environment()->FastForwardBy(base::Milliseconds(500));
  EXPECT_EQ(error, blink::mojom::ShareError::CANCELED);
}

TEST_F(SharesheetClientUnitTest, TestWithoutFilesInIncognito) {
  SetIncognito();
  SharesheetClient sharesheet_client(web_contents());

  const std::string title = "Subject";
  const std::string text = "Message";
  const GURL share_url("https://example.com/");
  std::vector<blink::mojom::SharedFilePtr> files;

  base::RunLoop run_loop;
  blink::mojom::ShareError error = blink::mojom::ShareError::INTERNAL_ERROR;
  sharesheet_client.Share(
      title, text, share_url, std::move(files),
      base::BindLambdaForTesting(
          [&run_loop, &error](blink::mojom::ShareError in_error) {
            error = in_error;
            run_loop.Quit();
          }));

  run_loop.Run();
  EXPECT_EQ(error, blink::mojom::ShareError::OK);
}

TEST_F(SharesheetClientUnitTest, DeleteAfterShare) {
  SetGuest();
  SharesheetClient sharesheet_client(web_contents());
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  base::FilePath share_cache_dir;
  ASSERT_TRUE(chrome::GetShareCachePath(&share_cache_dir));
  const base::FilePath first_file =
      share_cache_dir.AppendASCII(".web_share/share1/first.txt");
  const base::FilePath second_file =
      share_cache_dir.AppendASCII(".web_share/share2/second.txt");
#else
  const base::FilePath share_cache_dir =
      file_manager::util::GetShareCacheFilePath(profile());
  const base::FilePath first_file =
      share_cache_dir.AppendASCII(".WebShare/share1/first.txt");
  const base::FilePath second_file =
      share_cache_dir.AppendASCII(".WebShare/share2/second.txt");
#endif
  const std::string title = "Subject";
  const std::string text = "Message";
  const GURL share_url("https://example.com/");
  std::vector<blink::mojom::SharedFilePtr> files;
  files.push_back(
      blink::mojom::SharedFile::New(*base::SafeBaseName::Create(first_file),
                                    blink::mojom::SerializedBlob::New()));
  files.push_back(
      blink::mojom::SharedFile::New(*base::SafeBaseName::Create(second_file),
                                    blink::mojom::SerializedBlob::New()));

  base::RunLoop run_loop;
  blink::mojom::ShareError error = blink::mojom::ShareError::INTERNAL_ERROR;
  sharesheet_client.Share(
      title, text, share_url, std::move(files),
      base::BindLambdaForTesting(
          [&run_loop, &error](blink::mojom::ShareError in_error) {
            error = in_error;
            run_loop.Quit();
          }));

  run_loop.Run();
  EXPECT_EQ(error, blink::mojom::ShareError::OK);

  task_environment()->FastForwardBy(PrepareDirectoryTask::kSharedFileLifetime /
                                    2);
  EXPECT_TRUE(base::PathExists(first_file));
  EXPECT_TRUE(base::PathExists(second_file));

  task_environment()->FastForwardBy(PrepareDirectoryTask::kSharedFileLifetime *
                                    2);
  EXPECT_FALSE(base::PathExists(first_file));
  EXPECT_FALSE(base::PathExists(second_file));
}

}  // namespace webshare