#include "chrome/browser/platform_util.h"
#include <memory>
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/platform_util_internal.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "base/json/json_string_value_serializer.h"
#include "base/values.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/apps/app_service/app_service_test.h"
#include "chrome/browser/apps/app_service/intent_util.h"
#include "chrome/browser/ash/file_manager/app_id.h"
#include "chrome/browser/ash/fileapi/file_system_backend.h"
#include "chrome/browser/ash/fileapi/file_system_backend_delegate.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/extensions/extension_special_storage_policy.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "components/services/app_service/public/cpp/app_types.h"
#include "components/services/app_service/public/cpp/intent_filter.h"
#include "content/public/browser/browser_context.h"
#include "content/public/common/content_client.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "storage/common/file_system/file_system_types.h"
#else
#include "content/public/test/browser_task_environment.h"
#endif
namespace platform_util {
namespace {
#if BUILDFLAG(IS_CHROMEOS_ASH)
class PlatformUtilTestContentBrowserClient : public ChromeContentBrowserClient {
public:
void GetAdditionalFileSystemBackends(
content::BrowserContext* browser_context,
const base::FilePath& storage_partition_path,
std::vector<std::unique_ptr<storage::FileSystemBackend>>*
additional_backends) override {
storage::ExternalMountPoints* external_mount_points =
browser_context->GetMountPoints();
additional_backends->push_back(std::make_unique<ash::FileSystemBackend>(
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
external_mount_points,
storage::ExternalMountPoints::GetSystemInstance()));
}
};
class PlatformUtilTestBase : public BrowserWithTestWindowTest {
protected:
void SetUpPlatformFixture(const base::FilePath& test_directory) {
content_browser_client_ =
std::make_unique<PlatformUtilTestContentBrowserClient>();
old_content_browser_client_ =
content::SetBrowserClientForTesting(content_browser_client_.get());
app_service_test_.SetUp(GetProfile());
app_service_proxy_ =
apps::AppServiceProxyFactory::GetForProfile(GetProfile());
ASSERT_TRUE(app_service_proxy_);
GetProfile()->GetMountPoints()->RegisterFileSystem(
"test", storage::kFileSystemTypeLocal, storage::FileSystemMountOption(),
test_directory);
std::string error;
int error_code = 0;
std::string json_manifest =
"{"
" \"manifest_version\": 2,"
" \"name\": \"Test extension\","
" \"version\": \"0\","
" \"app\": { \"background\": { \"scripts\": [\"main.js\"] }},"
" \"file_handlers\": {"
" \"text\": {"
" \"extensions\": [ \"txt\" ],"
" \"title\": \"Text\""
" }"
" }"
"}";
JSONStringValueDeserializer json_string_deserializer(json_manifest);
std::unique_ptr<base::Value> manifest =
json_string_deserializer.Deserialize(&error_code, &error);
base::Value::Dict* manifest_dictionary = manifest->GetIfDict();
ASSERT_TRUE(manifest_dictionary);
scoped_refptr<extensions::Extension> extension =
extensions::Extension::Create(
test_directory.AppendASCII("invalid-extension"),
extensions::mojom::ManifestLocation::kInvalidLocation,
*manifest_dictionary, extensions::Extension::NO_FLAGS, &error);
ASSERT_TRUE(error.empty()) << error;
std::vector<apps::AppPtr> apps;
auto app = std::make_unique<apps::App>(apps::AppType::kChromeApp,
"invalid-chrome-app");
app->handles_intents = true;
app->readiness = apps::Readiness::kReady;
app->intent_filters =
apps_util::CreateIntentFiltersForChromeApp(extension.get());
apps.push_back(std::move(app));
app_service_proxy_->OnApps(std::move(apps), apps::AppType::kChromeApp,
false);
}
void SetUp() override {
BrowserWithTestWindowTest::SetUp();
base::RunLoop().RunUntilIdle();
}
void TearDown() override {
content::ContentBrowserClient* content_browser_client =
content::SetBrowserClientForTesting(old_content_browser_client_);
old_content_browser_client_ = nullptr;
DCHECK_EQ(static_cast<content::ContentBrowserClient*>(
content_browser_client_.get()),
content_browser_client)
<< "ContentBrowserClient changed during test.";
BrowserWithTestWindowTest::TearDown();
}
private:
std::unique_ptr<content::ContentBrowserClient> content_browser_client_;
raw_ptr<content::ContentBrowserClient> old_content_browser_client_ = nullptr;
apps::AppServiceTest app_service_test_;
raw_ptr<apps::AppServiceProxy, DanglingUntriaged> app_service_proxy_ =
nullptr;
};
#else
class PlatformUtilTestBase : public testing::Test { … };
#endif
class PlatformUtilTest : public PlatformUtilTestBase { … };
}
TEST_F(PlatformUtilTest, OpenFile) { … }
TEST_F(PlatformUtilTest, OpenFolder) { … }
#if BUILDFLAG(IS_POSIX)
class PlatformUtilPosixTest : public PlatformUtilTest { … };
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(PlatformUtilPosixTest, OpenFileWithPosixSymlinksChromeOS) {
EXPECT_EQ(OPEN_FAILED_PATH_NOT_FOUND,
CallOpenItem(symlink_to_file_, OPEN_FILE));
EXPECT_EQ(OPEN_FAILED_PATH_NOT_FOUND,
CallOpenItem(symlink_to_folder_, OPEN_FILE));
EXPECT_EQ(OPEN_FAILED_PATH_NOT_FOUND,
CallOpenItem(symlink_to_nowhere_, OPEN_FILE));
}
TEST_F(PlatformUtilPosixTest, OpenFolderWithPosixSymlinksChromeOS) {
EXPECT_EQ(OPEN_FAILED_PATH_NOT_FOUND,
CallOpenItem(symlink_to_folder_, OPEN_FOLDER));
EXPECT_EQ(OPEN_FAILED_PATH_NOT_FOUND,
CallOpenItem(symlink_to_file_, OPEN_FOLDER));
EXPECT_EQ(OPEN_FAILED_PATH_NOT_FOUND,
CallOpenItem(symlink_to_nowhere_, OPEN_FOLDER));
}
TEST_F(PlatformUtilTest, OpenFileWithUnhandledFileType) {
base::FilePath unhandled_file =
directory_.GetPath().AppendASCII("myfile.filetype");
ASSERT_TRUE(base::WriteFile(unhandled_file, "cat"));
EXPECT_EQ(OPEN_FAILED_NO_HANLDER_FOR_FILE_TYPE,
CallOpenItem(unhandled_file, OPEN_FILE));
}
#endif
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(PlatformUtilPosixTest, OpenFileWithPosixSymlinks) { … }
TEST_F(PlatformUtilPosixTest, OpenFolderWithPosixSymlinks) { … }
#endif
}