// 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/apps/app_service/file_utils.h"
#include <memory>
#include <string>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "base/files/file_path.h"
#include "base/strings/strcat.h"
#include "chrome/browser/ash/file_manager/fileapi_util.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/common/extension.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "storage/browser/file_system/file_system_url.h"
#include "storage/common/file_system/file_system_util.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/gurl.h"
#include "url/origin.h"
#include "url/url_constants.h"
namespace apps {
namespace {
using ::testing::ElementsAre;
using ::testing::IsEmpty;
class FileUtilsTest : public ::testing::Test {
public:
void SetUp() override {
testing::Test::SetUp();
profile_manager_ = std::make_unique<TestingProfileManager>(
TestingBrowserProcess::GetGlobal());
ASSERT_TRUE(profile_manager_->SetUp());
profile_ = profile_manager_->CreateTestingProfile("testing_profile");
ASSERT_TRUE(
storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
mount_name_, storage::FileSystemType::kFileSystemTypeExternal,
storage::FileSystemMountOption(), base::FilePath(fs_root_)));
ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
}
void TearDown() override {
ASSERT_TRUE(
storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
mount_name_));
profile_ = nullptr;
profile_manager_->DeleteAllTestingProfiles();
profile_manager_.reset();
}
TestingProfile* GetProfile() { return profile_; }
base::FilePath GetTempDir() { return scoped_temp_dir_.GetPath(); }
// FileUtils explicitly relies on ChromeOS Files.app for files manipulation.
const url::Origin GetFileManagerOrigin() {
return url::Origin::Create(file_manager::util::GetFileManagerURL());
}
// Converts the given virtual |path| to a file system URL. Uses test file
// system type.
storage::FileSystemURL ToTestFileSystemURL(const std::string& path) {
return storage::FileSystemURL::CreateForTest(
blink::StorageKey::CreateFirstParty(GetFileManagerOrigin()),
storage::FileSystemType::kFileSystemTypeTest, base::FilePath(path));
}
// For a given |root| converts the given virtual |path| to a GURL.
GURL ToGURL(const base::FilePath& root, const std::string& path) {
const std::string abs_path = root.Append(path).value();
return GURL(base::StrCat({url::kFileSystemScheme, ":",
GetFileManagerOrigin().Serialize(), abs_path}));
}
protected:
const std::string mount_name_ = "TestMountName";
const std::string fs_root_ = "/path/to/test/filesystemroot";
private:
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestingProfileManager> profile_manager_;
base::ScopedTempDir scoped_temp_dir_;
raw_ptr<TestingProfile> profile_ = nullptr;
};
TEST_F(FileUtilsTest, GetFileSystemURL) {
std::vector<GURL> url_list;
std::vector<storage::FileSystemURL> fsurl_list;
// Case 1: url_list is empty.
fsurl_list = GetFileSystemURL(GetProfile(), url_list);
EXPECT_THAT(fsurl_list, IsEmpty());
// Case 2: url_list contains a GURL.
const std::string path = "Documents/foo.txt";
url_list.push_back(ToGURL(base::FilePath(storage::kTestDir), path));
fsurl_list = GetFileSystemURL(GetProfile(), url_list);
EXPECT_THAT(fsurl_list, ElementsAre(ToTestFileSystemURL(path)));
}
TEST_F(FileUtilsTest, GetFileSystemUrls) {
std::vector<GURL> url_list;
std::vector<base::FilePath> fp_list;
// Case 1: fp_list is empty.
url_list = GetFileSystemUrls(GetProfile(), fp_list);
EXPECT_THAT(url_list, IsEmpty());
// Case 2: fp_list contain some paths.
const std::string path = "Images/foo.jpg";
fp_list.push_back(base::FilePath(fs_root_).Append(path));
url_list = GetFileSystemUrls(GetProfile(), fp_list);
// Given a list of absolute file paths, return a list of filesystem:// URLs
// that use the kFileSystemTypeExternal type with Files Manager's origin.
// TODO(crbug.com/40763788): The use of Files Manager origin in these URLs is
// probably incorrect and should be revisited.
EXPECT_THAT(
url_list,
ElementsAre(ToGURL(
base::FilePath(storage::kExternalDir).Append(mount_name_), path)));
// Case 3: paths not originating in a known root are ignored.
fp_list.push_back(base::FilePath("/not/a/known/root").Append(path));
url_list = GetFileSystemUrls(GetProfile(), fp_list);
// Still just one path corresponding to foo.jpg under a known root.
EXPECT_THAT(
url_list,
ElementsAre(ToGURL(
base::FilePath(storage::kExternalDir).Append(mount_name_), path)));
}
TEST_F(FileUtilsTest, GetSingleFileSystemURL) {
GURL url;
storage::FileSystemURL fsurl;
const std::string path = "Documents/foo.txt";
url = ToGURL(base::FilePath(storage::kTestDir), path);
fsurl = GetFileSystemURL(GetProfile(), url);
EXPECT_EQ(fsurl, ToTestFileSystemURL(path));
}
TEST_F(FileUtilsTest, GetSingleFileSystemUrl) {
GURL url;
base::FilePath file_path;
const std::string path = "Images/foo.jpg";
file_path = base::FilePath(fs_root_).Append(path);
url = GetFileSystemUrl(GetProfile(), file_path);
EXPECT_EQ(
url,
ToGURL(base::FilePath(storage::kExternalDir).Append(mount_name_), path));
}
} // namespace
} // namespace apps