// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "ash/constants/ash_features.h"
#include "base/base64.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "chrome/browser/ash/crostini/crostini_manager.h"
#include "chrome/browser/ash/crostini/crostini_pref_names.h"
#include "chrome/browser/ash/crostini/fake_crostini_features.h"
#include "chrome/browser/ash/drive/drivefs_test_support.h"
#include "chrome/browser/ash/extensions/file_manager/event_router.h"
#include "chrome/browser/ash/extensions/file_manager/event_router_factory.h"
#include "chrome/browser/ash/extensions/file_manager/private_api_misc.h"
#include "chrome/browser/ash/extensions/file_manager/select_file_dialog_extension_user_data.h"
#include "chrome/browser/ash/file_manager/file_watcher.h"
#include "chrome/browser/ash/file_manager/mount_test_util.h"
#include "chrome/browser/ash/file_manager/path_util.h"
#include "chrome/browser/ash/file_manager/volume_manager.h"
#include "chrome/browser/ash/file_system_provider/icon_set.h"
#include "chrome/browser/ash/file_system_provider/provided_file_system_info.h"
#include "chrome/browser/ash/fileapi/file_system_backend.h"
#include "chrome/browser/ash/policy/dlp/dialogs/files_policy_dialog.h"
#include "chrome/browser/ash/policy/dlp/dlp_files_controller_ash.h"
#include "chrome/browser/ash/policy/dlp/files_policy_notification_manager.h"
#include "chrome/browser/ash/policy/dlp/files_policy_notification_manager_factory.h"
#include "chrome/browser/ash/policy/dlp/test/mock_files_policy_notification_manager.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_file_destination.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h"
#include "chrome/browser/chromeos/policy/dlp/test/mock_dlp_rules_manager.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/api/file_system_provider_capabilities/file_system_provider_capabilities_handler.h"
#include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h"
#include "chromeos/ash/components/dbus/vm_concierge/concierge_service.pb.h"
#include "chromeos/ash/components/disks/disk.h"
#include "chromeos/ash/components/disks/mock_disk_mount_manager.h"
#include "chromeos/dbus/dlp/dlp_client.h"
#include "chromeos/dbus/dlp/dlp_service.pb.h"
#include "components/drive/drive_pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_navigation_observer.h"
#include "extensions/browser/api_test_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/install_warning.h"
#include "google_apis/common/test_util.h"
#include "storage/browser/file_system/external_mount_points.h"
using ::testing::_;
using ::testing::ReturnRef;
namespace {
using ::ash::disks::Disk;
using ::ash::disks::DiskMountManager;
using ::ash::disks::FormatFileSystemType;
struct TestDiskInfo {
const char* file_path;
bool write_disabled_by_policy;
const char* device_label;
const char* drive_label;
const char* vendor_id;
const char* vendor_name;
const char* product_id;
const char* product_name;
const char* fs_uuid;
const char* storage_device_path;
ash::DeviceType device_type;
uint64_t size_in_bytes;
bool is_parent;
bool is_read_only_hardware;
bool has_media;
bool on_boot_device;
bool on_removable_device;
bool is_hidden;
const char* file_system_type;
const char* base_mount_path;
};
struct TestMountPoint {
std::string source_path;
std::string mount_path;
ash::MountType mount_type;
ash::MountError mount_error;
// -1 if there is no disk info.
int disk_info_index;
};
TestDiskInfo kTestDisks[] = {{"file_path1",
false,
"device_label1",
"drive_label1",
"0123",
"vendor1",
"abcd",
"product1",
"FFFF-FFFF",
"storage_device_path1",
ash::DeviceType::kUSB,
1073741824,
false,
false,
false,
false,
false,
false,
"exfat",
""},
{"file_path2",
false,
"device_label2",
"drive_label2",
"4567",
"vendor2",
"cdef",
"product2",
"0FFF-FFFF",
"storage_device_path2",
ash::DeviceType::kMobile,
47723,
true,
true,
true,
true,
false,
false,
"exfat",
""},
{"file_path3",
true, // write_disabled_by_policy
"device_label3",
"drive_label3",
"89ab",
"vendor3",
"ef01",
"product3",
"00FF-FFFF",
"storage_device_path3",
ash::DeviceType::kOpticalDisc,
0,
true,
false, // is_hardware_read_only
false,
true,
false,
false,
"exfat",
""}};
const char kLocalMountPointName[] = "local";
void AddLocalFileSystem(Profile* profile, base::FilePath root) {
const char kTestFileContent[] = "The five boxing wizards jumped quickly";
{
base::ScopedAllowBlockingForTesting allow_io;
ASSERT_TRUE(base::CreateDirectory(root.AppendASCII("test_dir")));
ASSERT_TRUE(google_apis::test_util::WriteStringToFile(
root.AppendASCII("test_dir").AppendASCII("test_file.txt"),
kTestFileContent));
}
ASSERT_TRUE(profile->GetMountPoints()->RegisterFileSystem(
kLocalMountPointName, storage::kFileSystemTypeLocal,
storage::FileSystemMountOption(), root));
file_manager::VolumeManager::Get(profile)->AddVolumeForTesting(
root, file_manager::VOLUME_TYPE_TESTING, ash::DeviceType::kUnknown,
false /* read_only */);
}
} // namespace
class FileManagerPrivateApiTest : public extensions::ExtensionApiTest {
public:
FileManagerPrivateApiTest() : disk_mount_manager_mock_(nullptr) {
InitMountPoints();
}
~FileManagerPrivateApiTest() override {
DCHECK(!disk_mount_manager_mock_);
DCHECK(!event_router_);
}
bool SetUpUserDataDirectory() override {
return drive::SetUpUserDataDirectoryForDriveFsTest();
}
void SetUpOnMainThread() override {
extensions::ExtensionApiTest::SetUpOnMainThread();
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
ASSERT_TRUE(non_watchable_dir_.CreateUniqueTempDir());
event_router_ = file_manager::EventRouterFactory::GetForProfile(profile());
}
void TearDownOnMainThread() override {
event_router_ = nullptr;
extensions::ExtensionApiTest::TearDownOnMainThread();
}
// ExtensionApiTest override
void SetUpInProcessBrowserTestFixture() override {
extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture();
disk_mount_manager_mock_ = new ash::disks::MockDiskMountManager;
DiskMountManager::InitializeForTesting(disk_mount_manager_mock_);
disk_mount_manager_mock_->SetupDefaultReplies();
// override mock functions.
ON_CALL(*disk_mount_manager_mock_, FindDiskBySourcePath(_))
.WillByDefault(
Invoke(this, &FileManagerPrivateApiTest::FindVolumeBySourcePath));
EXPECT_CALL(*disk_mount_manager_mock_, disks())
.WillRepeatedly(ReturnRef(volumes_));
EXPECT_CALL(*disk_mount_manager_mock_, mount_points())
.WillRepeatedly(ReturnRef(mount_points_));
}
// ExtensionApiTest override
void TearDownInProcessBrowserTestFixture() override {
DiskMountManager::Shutdown();
disk_mount_manager_mock_ = nullptr;
extensions::ExtensionApiTest::TearDownInProcessBrowserTestFixture();
}
private:
void InitMountPoints() {
const TestMountPoint kTestMountPoints[] = {
{"device_path1",
ash::CrosDisksClient::GetRemovableDiskMountPoint()
.AppendASCII("mount_path1")
.AsUTF8Unsafe(),
ash::MountType::kDevice, ash::MountError::kSuccess, 0},
{"device_path2",
ash::CrosDisksClient::GetRemovableDiskMountPoint()
.AppendASCII("mount_path2")
.AsUTF8Unsafe(),
ash::MountType::kDevice, ash::MountError::kSuccess, 1},
{"device_path3",
ash::CrosDisksClient::GetRemovableDiskMountPoint()
.AppendASCII("mount_path3")
.AsUTF8Unsafe(),
ash::MountType::kDevice, ash::MountError::kSuccess, 2},
{// Set source path inside another mounted volume.
ash::CrosDisksClient::GetRemovableDiskMountPoint()
.AppendASCII("mount_path3/archive.zip")
.AsUTF8Unsafe(),
ash::CrosDisksClient::GetArchiveMountPoint()
.AppendASCII("archive_mount_path")
.AsUTF8Unsafe(),
ash::MountType::kArchive, ash::MountError::kSuccess, -1}};
for (const auto& mp : kTestMountPoints) {
mount_points_.insert(
{mp.source_path, mp.mount_path, mp.mount_type, mp.mount_error});
int disk_info_index = mp.disk_info_index;
if (mp.disk_info_index >= 0) {
EXPECT_GT(std::size(kTestDisks), static_cast<size_t>(disk_info_index));
if (static_cast<size_t>(disk_info_index) >= std::size(kTestDisks)) {
return;
}
std::unique_ptr<Disk> disk =
Disk::Builder()
.SetDevicePath(mp.source_path)
.SetMountPath(mp.mount_path)
.SetWriteDisabledByPolicy(
kTestDisks[disk_info_index].write_disabled_by_policy)
.SetFilePath(kTestDisks[disk_info_index].file_path)
.SetDeviceLabel(kTestDisks[disk_info_index].device_label)
.SetDriveLabel(kTestDisks[disk_info_index].drive_label)
.SetVendorId(kTestDisks[disk_info_index].vendor_id)
.SetVendorName(kTestDisks[disk_info_index].vendor_name)
.SetProductId(kTestDisks[disk_info_index].product_id)
.SetProductName(kTestDisks[disk_info_index].product_name)
.SetFileSystemUUID(kTestDisks[disk_info_index].fs_uuid)
.SetStorageDevicePath(
kTestDisks[disk_info_index].storage_device_path)
.SetDeviceType(kTestDisks[disk_info_index].device_type)
.SetSizeInBytes(kTestDisks[disk_info_index].size_in_bytes)
.SetIsParent(kTestDisks[disk_info_index].is_parent)
.SetIsReadOnlyHardware(
kTestDisks[disk_info_index].is_read_only_hardware)
.SetHasMedia(kTestDisks[disk_info_index].has_media)
.SetOnBootDevice(kTestDisks[disk_info_index].on_boot_device)
.SetOnRemovableDevice(
kTestDisks[disk_info_index].on_removable_device)
.SetIsHidden(kTestDisks[disk_info_index].is_hidden)
.SetFileSystemType(kTestDisks[disk_info_index].file_system_type)
.SetBaseMountPath(kTestDisks[disk_info_index].base_mount_path)
.Build();
volumes_.insert(std::move(disk));
}
}
}
const Disk* FindVolumeBySourcePath(const std::string& source_path) {
auto volume_it = volumes_.find(source_path);
return (volume_it == volumes_.end()) ? nullptr : volume_it->get();
}
protected:
void SshfsMount(const std::string& source_path,
const std::string& source_format,
const std::string& mount_label,
const std::vector<std::string>& mount_options,
ash::MountType type,
ash::MountAccessMode access_mode,
DiskMountManager::MountPathCallback callback) {
DiskMountManager::MountPoint mount_point_info{
source_path, "/media/fuse/" + mount_label,
ash::MountType::kNetworkStorage};
disk_mount_manager_mock_->NotifyMountEvent(
DiskMountManager::MountEvent::MOUNTING, ash::MountError::kSuccess,
mount_point_info);
std::move(callback).Run(ash::MountError::kSuccess, mount_point_info);
}
void ExpectCrostiniMount() {
std::vector<std::string> mount_options;
EXPECT_CALL(*disk_mount_manager_mock_,
MountPath("sftp://3:1234", "", "crostini_user_termina_penguin",
mount_options, ash::MountType::kNetworkStorage,
ash::MountAccessMode::kReadWrite, _))
.WillOnce(Invoke(this, &FileManagerPrivateApiTest::SshfsMount));
}
base::ScopedTempDir temp_dir_;
base::ScopedTempDir non_watchable_dir_;
raw_ptr<ash::disks::MockDiskMountManager, DanglingUntriaged>
disk_mount_manager_mock_ = nullptr;
DiskMountManager::Disks volumes_;
DiskMountManager::MountPoints mount_points_;
raw_ptr<file_manager::EventRouter> event_router_ = nullptr;
};
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, Mount) {
using ash::file_system_provider::IconSet;
profile()->GetPrefs()->SetBoolean(drive::prefs::kDisableDrive, true);
// Add a provided file system, to test passing the |configurable| and
// |source| flags properly down to Files app.
IconSet icon_set;
icon_set.SetIcon(IconSet::IconSize::SIZE_16x16,
GURL("chrome://resources/testing-provider-id-16.jpg"));
icon_set.SetIcon(IconSet::IconSize::SIZE_32x32,
GURL("chrome://resources/testing-provider-id-32.jpg"));
ash::file_system_provider::ProvidedFileSystemInfo info(
"testing-provider-id", ash::file_system_provider::MountOptions(),
base::FilePath(), true /* configurable */, false /* watchable */,
extensions::SOURCE_NETWORK, icon_set);
file_manager::VolumeManager::Get(browser()->profile())
->AddVolumeForTesting(file_manager::Volume::CreateForProvidedFileSystem(
info, file_manager::MOUNT_CONTEXT_AUTO));
// The test.js calls fileManagerPrivate.removeMount(name) twice for each name
// "mount_path1" and "archive_mount_path". The first call should unmount with
// no error, and the second should fail with an error. Record the events, and
// verify them by name and occurrence count.
int events[4] = {0, 0, 0, 0};
EXPECT_CALL(*disk_mount_manager_mock_,
UnmountPath(ash::CrosDisksClient::GetRemovableDiskMountPoint()
.AppendASCII("mount_path1")
.AsUTF8Unsafe(),
_))
.WillOnce(testing::Invoke(
[&events](const std::string& path,
DiskMountManager::UnmountPathCallback callback) {
const auto name = base::FilePath(path).BaseName();
EXPECT_EQ("mount_path1", name.value());
++events[0];
EXPECT_EQ(1, events[0]);
std::move(callback).Run(ash::MountError::kSuccess);
}))
.WillOnce(testing::Invoke(
[&events](const std::string& path,
DiskMountManager::UnmountPathCallback callback) {
const auto name = base::FilePath(path).BaseName();
EXPECT_EQ("mount_path1", name.value());
++events[1];
EXPECT_EQ(1, events[1]);
std::move(callback).Run(ash::MountError::kCancelled);
}));
EXPECT_CALL(*disk_mount_manager_mock_,
UnmountPath(ash::CrosDisksClient::GetArchiveMountPoint()
.AppendASCII("archive_mount_path")
.AsUTF8Unsafe(),
_))
.WillOnce(testing::Invoke(
[&events](const std::string& path,
DiskMountManager::UnmountPathCallback callback) {
const auto name = base::FilePath(path).BaseName();
EXPECT_EQ("archive_mount_path", name.value());
++events[2];
EXPECT_EQ(1, events[2]);
std::move(callback).Run(ash::MountError::kSuccess);
}))
.WillOnce(testing::Invoke(
[&events](const std::string& path,
DiskMountManager::UnmountPathCallback callback) {
const auto name = base::FilePath(path).BaseName();
EXPECT_EQ("archive_mount_path", name.value());
++events[3];
EXPECT_EQ(1, events[3]);
std::move(callback).Run(ash::MountError::kNeedPassword);
}));
ASSERT_TRUE(RunExtensionTest("file_browser/mount_test", {},
{.load_as_component = true}))
<< message_;
ASSERT_EQ(1, events[0]);
ASSERT_EQ(1, events[1]);
ASSERT_EQ(1, events[2]);
ASSERT_EQ(1, events[3]);
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, FormatVolume) {
// Catch-all rule to ensure that FormatMountedDevice does not get called with
// other arguments that don't match the rules below.
EXPECT_CALL(*disk_mount_manager_mock_, FormatMountedDevice(_, _, _)).Times(0);
EXPECT_CALL(
*disk_mount_manager_mock_,
FormatMountedDevice(ash::CrosDisksClient::GetRemovableDiskMountPoint()
.AppendASCII("mount_path1")
.AsUTF8Unsafe(),
FormatFileSystemType::kVfat, "NEWLABEL1"))
.Times(1);
EXPECT_CALL(
*disk_mount_manager_mock_,
FormatMountedDevice(ash::CrosDisksClient::GetRemovableDiskMountPoint()
.AppendASCII("mount_path2")
.AsUTF8Unsafe(),
FormatFileSystemType::kExfat, "NEWLABEL2"))
.Times(1);
EXPECT_CALL(
*disk_mount_manager_mock_,
FormatMountedDevice(ash::CrosDisksClient::GetRemovableDiskMountPoint()
.AppendASCII("mount_path3")
.AsUTF8Unsafe(),
FormatFileSystemType::kNtfs, "NEWLABEL3"))
.Times(1);
ASSERT_TRUE(RunExtensionTest("file_browser/format_test", {},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, Permissions) {
EXPECT_TRUE(RunExtensionTest("file_browser/permissions", {},
{.ignore_manifest_warnings = true}));
const extensions::Extension* extension = GetSingleLoadedExtension();
ASSERT_TRUE(extension);
ASSERT_EQ(1u, extension->install_warnings().size());
const extensions::InstallWarning& warning = extension->install_warnings()[0];
EXPECT_EQ("fileManagerPrivate", warning.key);
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, AddFileWatch) {
// Add a filesystem and Volume that is not watchable.
AddLocalFileSystem(browser()->profile(), non_watchable_dir_.GetPath());
// Add a filesystem and Volume that is watchable.
const base::FilePath downloads_dir = temp_dir_.GetPath();
ASSERT_TRUE(file_manager::VolumeManager::Get(browser()->profile())
->RegisterDownloadsDirectoryForTesting(downloads_dir));
ASSERT_TRUE(RunExtensionTest("file_browser/add_file_watch", {},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, Recent) {
const base::FilePath downloads_dir = temp_dir_.GetPath();
ASSERT_TRUE(file_manager::VolumeManager::Get(browser()->profile())
->RegisterDownloadsDirectoryForTesting(downloads_dir));
// Create test files.
{
base::ScopedAllowBlockingForTesting allow_io;
base::File image_file(downloads_dir.Append("all-justice.jpg"),
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(image_file.IsValid());
base::File audio_file(downloads_dir.Append("all-justice.mp3"),
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(audio_file.IsValid());
base::File video_file(downloads_dir.Append("all-justice.mp4"),
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(video_file.IsValid());
base::File text_file(downloads_dir.Append("all-justice.txt"),
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(text_file.IsValid());
ASSERT_TRUE(text_file.SetTimes(base::Time::Now(),
base::Time::Now() - base::Days(60)));
}
ASSERT_TRUE(RunExtensionTest("file_browser/recent_test", {},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, MediaMetadata) {
const base::FilePath test_dir = temp_dir_.GetPath();
AddLocalFileSystem(browser()->profile(), test_dir);
// Get source media/test/data directory path.
base::FilePath root_dir;
CHECK(base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &root_dir));
const base::FilePath media_test_data_dir =
root_dir.AppendASCII("media").AppendASCII("test").AppendASCII("data");
// Returns a path to a media/test/data test file.
auto get_media_test_data_file = [&](const std::string& file) {
return media_test_data_dir.Append(base::FilePath::FromUTF8Unsafe(file));
};
// Create media test files.
{
base::ScopedAllowBlockingForTesting allow_io;
const base::FilePath video = get_media_test_data_file("90rotation.mp4");
ASSERT_TRUE(base::CopyFile(video, test_dir.Append(video.BaseName())));
const base::FilePath audio = get_media_test_data_file("id3_png_test.mp3");
ASSERT_TRUE(base::CopyFile(audio, test_dir.Append(audio.BaseName())));
}
// Get source chrome/test/data/chromeos/file_manager directory path.
const base::FilePath files_test_data_dir = root_dir.AppendASCII("chrome")
.AppendASCII("test")
.AppendASCII("data")
.AppendASCII("chromeos")
.AppendASCII("file_manager");
// Returns a path to a chrome/test/data/chromeos/file_manager test file.
auto get_files_test_data_dir = [&](const std::string& file) {
return files_test_data_dir.Append(base::FilePath::FromUTF8Unsafe(file));
};
// Create files test files.
{
base::ScopedAllowBlockingForTesting allow_io;
const base::FilePath broke = get_files_test_data_dir("broken.jpg");
ASSERT_TRUE(base::CopyFile(broke, test_dir.Append(broke.BaseName())));
const base::FilePath empty = get_files_test_data_dir("empty.txt");
ASSERT_TRUE(base::CopyFile(empty, test_dir.Append(empty.BaseName())));
const base::FilePath image = get_files_test_data_dir("image3.jpg");
ASSERT_TRUE(base::CopyFile(image, test_dir.Append(image.BaseName())));
}
ASSERT_TRUE(RunExtensionTest("file_browser/media_metadata", {},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, Crostini) {
crostini::FakeCrostiniFeatures crostini_features;
crostini_features.set_is_allowed_now(true);
crostini_features.set_enabled(true);
// Setup CrostiniManager for testing.
crostini::CrostiniManager* crostini_manager =
crostini::CrostiniManager::GetForProfile(browser()->profile());
crostini_manager->set_skip_restart_for_testing();
crostini_manager->AddRunningVmForTesting(crostini::kCrostiniDefaultVmName, 3);
crostini_manager->AddRunningContainerForTesting(
crostini::kCrostiniDefaultVmName,
crostini::ContainerInfo(crostini::kCrostiniDefaultContainerName,
"testuser", "/home/testuser", "PLACEHOLDER_IP",
1234));
ExpectCrostiniMount();
// Add 'testing' volume with 'test_dir', create 'share_dir' in Downloads.
AddLocalFileSystem(browser()->profile(), temp_dir_.GetPath());
base::FilePath downloads;
ASSERT_TRUE(
storage::ExternalMountPoints::GetSystemInstance()->GetRegisteredPath(
file_manager::util::GetDownloadsMountPointName(browser()->profile()),
&downloads));
// Setup prefs guest_os.paths_shared_to_vms.
base::FilePath shared1 = downloads.AppendASCII("shared1");
base::FilePath shared2 = downloads.AppendASCII("shared2");
{
base::ScopedAllowBlockingForTesting allow_io;
ASSERT_TRUE(base::CreateDirectory(downloads.AppendASCII("share_dir")));
ASSERT_TRUE(base::CreateDirectory(shared1));
ASSERT_TRUE(base::CreateDirectory(shared2));
}
guest_os::GuestOsSharePath* guest_os_share_path =
guest_os::GuestOsSharePath::GetForProfile(browser()->profile());
guest_os_share_path->RegisterPersistedPaths(crostini::kCrostiniDefaultVmName,
{shared1});
guest_os_share_path->RegisterPersistedPaths(crostini::kCrostiniDefaultVmName,
{shared2});
ASSERT_TRUE(RunExtensionTest("file_browser/crostini_test", {},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, CrostiniIncognito) {
crostini::FakeCrostiniFeatures crostini_features;
crostini_features.set_is_allowed_now(true);
crostini_features.set_enabled(true);
// Setup CrostiniManager for testing.
crostini::CrostiniManager* crostini_manager =
crostini::CrostiniManager::GetForProfile(browser()->profile());
crostini_manager->set_skip_restart_for_testing();
crostini_manager->AddRunningVmForTesting(crostini::kCrostiniDefaultVmName, 3);
crostini_manager->AddRunningContainerForTesting(
crostini::kCrostiniDefaultVmName,
crostini::ContainerInfo(crostini::kCrostiniDefaultContainerName,
"testuser", "/home/testuser", "PLACEHOLDER_IP",
1234));
ExpectCrostiniMount();
scoped_refptr<extensions::FileManagerPrivateMountCrostiniFunction> function(
new extensions::FileManagerPrivateMountCrostiniFunction());
// Use incognito profile.
function->SetBrowserContextForTesting(
browser()->profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true));
extensions::api_test_utils::SendResponseHelper response_helper(
function.get());
function->RunWithValidation().Execute();
response_helper.WaitForResponse();
EXPECT_TRUE(response_helper.GetResponse());
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, HoldingSpace) {
const base::FilePath test_dir = temp_dir_.GetPath();
AddLocalFileSystem(browser()->profile(), test_dir);
{
base::ScopedAllowBlockingForTesting allow_io;
base::File image_file(test_dir.Append("test_image.jpg"),
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(image_file.IsValid());
base::File audio_file(test_dir.Append("test_audio.mp3"),
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(audio_file.IsValid());
base::File video_file(test_dir.Append("test_video.mp4"),
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(video_file.IsValid());
}
EXPECT_TRUE(RunExtensionTest("file_browser/holding_space", {},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, GetVolumeRoot) {
AddLocalFileSystem(browser()->profile(), temp_dir_.GetPath());
ASSERT_TRUE(RunExtensionTest("file_browser/get_volume_root", {},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, OpenURL) {
const char* target_url = "https://www.google.com/";
content::TestNavigationObserver navigation_observer(GURL{target_url});
navigation_observer.StartWatchingNewWebContents();
ASSERT_TRUE(RunExtensionTest("file_browser/open_url",
{.custom_arg = target_url},
{.load_as_component = true}));
// Wait for navigation to finish.
navigation_observer.Wait();
// Check that the current active web contents points to the expected URL.
BrowserList* browser_list = BrowserList::GetInstance();
Browser* browser = browser_list->GetLastActive();
content::WebContents* active_web_contents =
browser->tab_strip_model()->GetActiveWebContents();
EXPECT_STREQ(target_url, active_web_contents->GetVisibleURL().spec().c_str());
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, SearchFiles) {
const base::FilePath downloads_dir = temp_dir_.GetPath();
ASSERT_TRUE(file_manager::VolumeManager::Get(browser()->profile())
->RegisterDownloadsDirectoryForTesting(downloads_dir));
{
base::ScopedAllowBlockingForTesting allow_io;
// Creates two files with the same prefix, in different locations.
base::File root_image_file(
downloads_dir.Append("foo.jpg"),
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(root_image_file.IsValid());
ASSERT_TRUE(base::CreateDirectory(downloads_dir.AppendASCII("images")));
base::File nested_image_file(
downloads_dir.Append("images").Append("foo.jpg"),
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(nested_image_file.IsValid());
// Creates two files with the same prefix, and different modified dates.
base::File jan_15_file(downloads_dir.Append("bar_15012020.jpg"),
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(jan_15_file.IsValid());
static constexpr base::Time::Exploded kJan152020Noon = {.year = 2020,
.month = 1,
.day_of_week = 3,
.day_of_month = 15,
.hour = 12};
base::Time jan_15_2020_noon;
ASSERT_TRUE(base::Time::FromUTCExploded(kJan152020Noon, &jan_15_2020_noon));
jan_15_file.SetTimes(jan_15_2020_noon, jan_15_2020_noon);
base::File jan_01_file(downloads_dir.Append("bar_01012020.jpg"),
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(jan_01_file.IsValid());
static constexpr base::Time::Exploded kJan012020Noon = {.year = 2020,
.month = 1,
.day_of_week = 3,
.day_of_month = 1,
.hour = 12};
base::Time jan_01_2020_noon;
ASSERT_TRUE(base::Time::FromUTCExploded(kJan012020Noon, &jan_01_2020_noon));
jan_01_file.SetTimes(jan_01_2020_noon, jan_01_2020_noon);
}
ASSERT_TRUE(RunExtensionTest("file_browser/search_files", {},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, GetPdfThumbnail) {
AddLocalFileSystem(browser()->profile(), temp_dir_.GetPath());
base::FilePath downloads;
ASSERT_TRUE(
storage::ExternalMountPoints::GetSystemInstance()->GetRegisteredPath(
file_manager::util::GetDownloadsMountPointName(browser()->profile()),
&downloads));
{
base::ScopedAllowBlockingForTesting allow_io;
base::FilePath source_dir =
base::PathService::CheckedGet(chrome::DIR_TEST_DATA).AppendASCII("pdf");
ASSERT_TRUE(base::CopyFile(source_dir.AppendASCII("test.pdf"),
downloads.AppendASCII("test.pdf")));
ASSERT_TRUE(base::CopyFile(source_dir.AppendASCII("combobox_form.pdf"),
downloads.AppendASCII("combobox_form.pdf")));
}
EXPECT_TRUE(RunExtensionTest("image_loader_private/get_pdf_thumbnail",
/*run_options=*/{},
/*load_options=*/{.load_as_component = true}));
}
class FileManagerPrivateApiDlpTest : public FileManagerPrivateApiTest {
public:
FileManagerPrivateApiDlpTest() {
scoped_feature_list_.InitAndEnableFeature(
features::kDataLeakPreventionFilesRestriction);
}
FileManagerPrivateApiDlpTest(const FileManagerPrivateApiDlpTest&) = delete;
void operator=(const FileManagerPrivateApiDlpTest&) = delete;
~FileManagerPrivateApiDlpTest() override = default;
void SetUpOnMainThread() override {
FileManagerPrivateApiTest::SetUpOnMainThread();
ASSERT_TRUE(drive_path_.CreateUniqueTempDir());
}
void TearDownOnMainThread() override {
// The files controller must be destroyed before the profile since it's
// holding a pointer to it.
files_controller_.reset();
mock_rules_manager_ = nullptr;
fpnm_ = nullptr;
FileManagerPrivateApiTest::TearDownOnMainThread();
}
std::unique_ptr<KeyedService> SetDlpRulesManager(
content::BrowserContext* context) {
auto dlp_rules_manager = std::make_unique<policy::MockDlpRulesManager>(
Profile::FromBrowserContext(context));
mock_rules_manager_ = dlp_rules_manager.get();
ON_CALL(*mock_rules_manager_, IsFilesPolicyEnabled)
.WillByDefault(testing::Return(true));
files_controller_ = std::make_unique<policy::DlpFilesControllerAsh>(
*mock_rules_manager_, Profile::FromBrowserContext(context));
ON_CALL(*mock_rules_manager_, GetDlpFilesController)
.WillByDefault(testing::Return(files_controller_.get()));
return dlp_rules_manager;
}
std::unique_ptr<KeyedService> SetFPNM(content::BrowserContext* context) {
auto fpnm = std::make_unique<policy::MockFilesPolicyNotificationManager>(
browser()->profile());
fpnm_ = fpnm.get();
return fpnm;
}
protected:
base::ScopedTempDir drive_path_;
raw_ptr<policy::MockDlpRulesManager, DanglingUntriaged> mock_rules_manager_ =
nullptr;
std::unique_ptr<policy::DlpFilesControllerAsh> files_controller_;
raw_ptr<policy::MockFilesPolicyNotificationManager, DanglingUntriaged> fpnm_;
base::test::ScopedFeatureList scoped_feature_list_;
};
class FileManagerPrivateApiDlpOldUXTest : public FileManagerPrivateApiDlpTest {
protected:
FileManagerPrivateApiDlpOldUXTest() {
scoped_feature_list_.Reset();
scoped_feature_list_.InitWithFeatures(
/*enabled_features=*/{features::kDataLeakPreventionFilesRestriction},
/*disabled_features=*/{features::kNewFilesPolicyUX});
}
FileManagerPrivateApiDlpOldUXTest(const FileManagerPrivateApiDlpOldUXTest&) =
delete;
void operator=(const FileManagerPrivateApiDlpOldUXTest&) = delete;
~FileManagerPrivateApiDlpOldUXTest() override = default;
};
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiDlpOldUXTest, DlpBlockCopy) {
policy::DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetDlpRulesManager,
base::Unretained(this)));
ASSERT_TRUE(policy::DlpRulesManagerFactory::GetForPrimaryProfile());
base::FilePath my_files_dir_ =
file_manager::util::GetMyFilesFolderForProfile(browser()->profile());
{
base::ScopedAllowBlockingForTesting allow_io;
ASSERT_TRUE(base::CreateDirectory(my_files_dir_));
}
AddLocalFileSystem(browser()->profile(), my_files_dir_);
const char kTestFileName[] = "dlp_test_file.txt";
const base::FilePath test_file_path = my_files_dir_.Append(kTestFileName);
{
base::ScopedAllowBlockingForTesting allow_io;
base::File test_file(test_file_path,
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(test_file.IsValid());
ASSERT_TRUE(base::CreateDirectory(drive_path_.GetPath().Append("subdir")));
}
auto* file_system_context =
file_manager::util::GetFileManagerFileSystemContext(browser()->profile());
ash::FileSystemBackend::Get(*file_system_context)
->GrantFileAccessToOrigin(
url::Origin::Create(
GURL("chrome-extension://"
"pkplfbidichfdicaijlchgnapepdginl/")), // Testing
// extension
base::FilePath(
base::StrCat({kLocalMountPointName, "/", kTestFileName})));
storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
"drivefs-delayed_mount_2", storage::kFileSystemTypeDriveFs,
storage::FileSystemMountOption(), drive_path_.GetPath());
file_manager::VolumeManager::Get(browser()->profile())
->AddVolumeForTesting( // IN-TEST
drive_path_.GetPath(), file_manager::VOLUME_TYPE_GOOGLE_DRIVE,
ash::DeviceType::kUnknown,
/*read_only=*/false);
dlp::CheckFilesTransferResponse check_files_response;
check_files_response.add_files_paths(test_file_path.value());
chromeos::DlpClient::Get()->GetTestInterface()->SetCheckFilesTransferResponse(
std::move(check_files_response));
EXPECT_CALL(*mock_rules_manager_, IsFilesPolicyEnabled)
.Times(testing::AnyNumber());
EXPECT_CALL(*mock_rules_manager_, GetDlpFilesController)
.Times(testing::AnyNumber());
EXPECT_TRUE(RunExtensionTest("file_browser/dlp_block", {},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiDlpTest, DlpMetadata) {
policy::DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetDlpRulesManager,
base::Unretained(this)));
ASSERT_TRUE(policy::DlpRulesManagerFactory::GetForPrimaryProfile());
EXPECT_CALL(*mock_rules_manager_, IsFilesPolicyEnabled).Times(1);
base::FilePath my_files_dir_ =
file_manager::util::GetMyFilesFolderForProfile(browser()->profile());
{
base::ScopedAllowBlockingForTesting allow_io;
ASSERT_TRUE(base::CreateDirectory(my_files_dir_));
}
AddLocalFileSystem(browser()->profile(), my_files_dir_);
const base::FilePath blocked_file_path =
my_files_dir_.Append("blocked_file.txt");
const base::FilePath unrestricted_file_path =
my_files_dir_.Append("unrestricted_file.txt");
const base::FilePath untracked_file_path =
my_files_dir_.Append("untracked_file.txt");
{
base::ScopedAllowBlockingForTesting allow_io;
base::File blocked_test_file(
blocked_file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(blocked_test_file.IsValid());
base::File unrestricted_test_file(
unrestricted_file_path,
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(unrestricted_test_file.IsValid());
base::File untracked_test_file(
untracked_file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(untracked_test_file.IsValid());
}
base::MockCallback<chromeos::DlpClient::AddFilesCallback> add_files_cb;
EXPECT_CALL(add_files_cb, Run).Times(1);
dlp::AddFilesRequest request;
dlp::AddFileRequest* file_request1 = request.add_add_file_requests();
file_request1->set_file_path(blocked_file_path.value());
file_request1->set_source_url("https://example1.com");
dlp::AddFileRequest* file_request2 = request.add_add_file_requests();
file_request2->set_file_path(unrestricted_file_path.value());
file_request2->set_source_url("https://example2.com");
chromeos::DlpClient::Get()->AddFiles(request, add_files_cb.Get());
EXPECT_CALL(*mock_rules_manager_, IsRestrictedByAnyRule)
.WillOnce(testing::Return(policy::DlpRulesManager::Level::kBlock))
.WillOnce(testing::Return(policy::DlpRulesManager::Level::kAllow))
.RetiresOnSaturation();
EXPECT_TRUE(RunExtensionTest("file_browser/dlp_metadata",
{.custom_arg = "default"},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiDlpTest, DlpRestrictionDetails) {
policy::DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetDlpRulesManager,
base::Unretained(this)));
ASSERT_TRUE(policy::DlpRulesManagerFactory::GetForPrimaryProfile());
EXPECT_CALL(*mock_rules_manager_, IsFilesPolicyEnabled).Times(1);
policy::DlpRulesManager::AggregatedDestinations destinations;
destinations[policy::DlpRulesManager::Level::kBlock].insert(
"https://external.com");
destinations[policy::DlpRulesManager::Level::kAllow].insert(
"https://internal.com");
policy::DlpRulesManager::AggregatedComponents components;
components[policy::DlpRulesManager::Level::kBlock].insert(
data_controls::Component::kArc);
components[policy::DlpRulesManager::Level::kBlock].insert(
data_controls::Component::kCrostini);
components[policy::DlpRulesManager::Level::kBlock].insert(
data_controls::Component::kPluginVm);
components[policy::DlpRulesManager::Level::kBlock].insert(
data_controls::Component::kUsb);
components[policy::DlpRulesManager::Level::kAllow].insert(
data_controls::Component::kDrive);
EXPECT_CALL(*mock_rules_manager_, GetAggregatedDestinations)
.WillOnce(testing::Return(destinations));
EXPECT_CALL(*mock_rules_manager_, GetAggregatedComponents)
.WillOnce(testing::Return(components));
EXPECT_TRUE(RunExtensionTest("file_browser/dlp_metadata",
{.custom_arg = "restriction_details"},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiDlpTest, DlpBlockedComponents) {
policy::DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetDlpRulesManager,
base::Unretained(this)));
ASSERT_TRUE(policy::DlpRulesManagerFactory::GetForPrimaryProfile());
EXPECT_CALL(*mock_rules_manager_, IsFilesPolicyEnabled).Times(1);
policy::DlpRulesManager::AggregatedComponents components;
components[policy::DlpRulesManager::Level::kBlock].insert(
data_controls::Component::kArc);
components[policy::DlpRulesManager::Level::kBlock].insert(
data_controls::Component::kCrostini);
components[policy::DlpRulesManager::Level::kBlock].insert(
data_controls::Component::kPluginVm);
components[policy::DlpRulesManager::Level::kBlock].insert(
data_controls::Component::kUsb);
components[policy::DlpRulesManager::Level::kAllow].insert(
data_controls::Component::kDrive);
EXPECT_CALL(*mock_rules_manager_, GetAggregatedComponents)
.WillOnce(testing::Return(components));
EXPECT_TRUE(RunExtensionTest("file_browser/dlp_metadata",
{.custom_arg = "blocked_components"},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiDlpTest, DlpMetadata_Disabled) {
policy::DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetDlpRulesManager,
base::Unretained(this)));
ASSERT_TRUE(policy::DlpRulesManagerFactory::GetForPrimaryProfile());
ON_CALL(*mock_rules_manager_, IsFilesPolicyEnabled)
.WillByDefault(testing::Return(false));
EXPECT_CALL(*mock_rules_manager_, IsFilesPolicyEnabled).Times(3);
// We should not get to the point of checking DLP.
EXPECT_CALL(*mock_rules_manager_, IsRestrictedByAnyRule).Times(0);
EXPECT_CALL(*mock_rules_manager_, GetAggregatedComponents).Times(0);
EXPECT_CALL(*mock_rules_manager_, GetAggregatedDestinations).Times(0);
AddLocalFileSystem(browser()->profile(), temp_dir_.GetPath());
const base::FilePath blocked_file_path =
temp_dir_.GetPath().Append("blocked_file.txt");
{
base::ScopedAllowBlockingForTesting allow_io;
base::File blocked_test_file(
blocked_file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(blocked_test_file.IsValid());
}
base::MockCallback<chromeos::DlpClient::AddFilesCallback> add_files_cb;
EXPECT_CALL(add_files_cb, Run).Times(1);
dlp::AddFilesRequest request;
dlp::AddFileRequest* file_request = request.add_add_file_requests();
file_request->set_file_path(blocked_file_path.value());
file_request->set_source_url("https://example1.com");
chromeos::DlpClient::Get()->AddFiles(request, add_files_cb.Get());
EXPECT_TRUE(RunExtensionTest("file_browser/dlp_metadata",
{.custom_arg = "disabled"},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiDlpTest, DlpMetadata_Error) {
policy::DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetDlpRulesManager,
base::Unretained(this)));
ASSERT_TRUE(policy::DlpRulesManagerFactory::GetForPrimaryProfile());
EXPECT_CALL(*mock_rules_manager_, IsFilesPolicyEnabled).Times(2);
// We should not get to the point of checking DLP.
EXPECT_CALL(*mock_rules_manager_, IsRestrictedByAnyRule).Times(0);
AddLocalFileSystem(browser()->profile(), temp_dir_.GetPath());
const base::FilePath blocked_file_path =
temp_dir_.GetPath().Append("blocked_file.txt");
{
base::ScopedAllowBlockingForTesting allow_io;
base::File blocked_test_file(
blocked_file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(blocked_test_file.IsValid());
}
base::MockCallback<chromeos::DlpClient::AddFilesCallback> add_files_cb;
EXPECT_CALL(add_files_cb, Run).Times(1);
dlp::AddFilesRequest request;
dlp::AddFileRequest* file_request = request.add_add_file_requests();
file_request->set_file_path(blocked_file_path.value());
file_request->set_source_url("https://example1.com");
chromeos::DlpClient::Get()->AddFiles(request, add_files_cb.Get());
EXPECT_TRUE(RunExtensionTest("file_browser/dlp_metadata",
{.custom_arg = "error"},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiDlpTest,
DlpMetadata_DismissIOTask) {
policy::DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetDlpRulesManager,
base::Unretained(this)));
ASSERT_TRUE(policy::DlpRulesManagerFactory::GetForPrimaryProfile());
EXPECT_CALL(*mock_rules_manager_, IsFilesPolicyEnabled).Times(0);
// We should not get to the point of checking DLP.
EXPECT_CALL(*mock_rules_manager_, IsRestrictedByAnyRule).Times(0);
policy::FilesPolicyNotificationManagerFactory::GetInstance()
->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetFPNM,
base::Unretained(this)));
// FPNM is created lazily so initialize it before running the test.
ASSERT_TRUE(
policy::FilesPolicyNotificationManagerFactory::GetForBrowserContext(
browser()->profile()));
// Expect only the valid task id.
EXPECT_CALL(*fpnm_, OnErrorItemDismissed(1u));
EXPECT_TRUE(RunExtensionTest("file_browser/dlp_metadata",
{.custom_arg = "dismissIOTask"},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiDlpTest,
DlpMetadata_ProgressPausedTasks) {
policy::DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetDlpRulesManager,
base::Unretained(this)));
ASSERT_TRUE(policy::DlpRulesManagerFactory::GetForPrimaryProfile());
EXPECT_CALL(*mock_rules_manager_, IsFilesPolicyEnabled).Times(0);
// We should not get to the point of checking DLP.
EXPECT_CALL(*mock_rules_manager_, IsRestrictedByAnyRule).Times(0);
std::vector<storage::FileSystemURL> source_urls{
storage::FileSystemURL::CreateForTest(
GURL("filesystem:chrome-extension://abc/external/foo/src")),
};
auto dest = storage::FileSystemURL::CreateForTest(
GURL("filesystem:chrome-extension://abc/external/foo/dest"));
file_manager::VolumeManager* const volume_manager =
file_manager::VolumeManager::Get(browser()->profile());
ASSERT_TRUE(volume_manager);
file_manager::io_task::IOTaskController* io_task_controller =
volume_manager->io_task_controller();
ASSERT_TRUE(io_task_controller);
// Create and pause the task.
auto task_id = io_task_controller->Add(
std::make_unique<file_manager::io_task::DummyIOTask>(
source_urls, dest, file_manager::io_task::OperationType::kCopy,
/*show_notification=*/true, /*progress_succeeds=*/false));
file_manager::io_task::PauseParams pause_params;
pause_params.policy_params =
file_manager::io_task::PolicyPauseParams(policy::Policy::kDlp);
io_task_controller->Pause(task_id, pause_params);
// Set up FPNM, but only after creating and pausing the task so that it would
// only get notified by the API call.
policy::FilesPolicyNotificationManagerFactory::GetInstance()
->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetFPNM,
base::Unretained(this)));
// FPNM is created lazily so initialize it before running the test.
ASSERT_TRUE(
policy::FilesPolicyNotificationManagerFactory::GetForBrowserContext(
browser()->profile()));
// Expect the pause status from ProgressPausedTasks.
EXPECT_CALL(
*fpnm_,
OnIOTaskStatus(AllOf(
testing::Field(&file_manager::io_task::ProgressStatus::task_id,
task_id),
testing::Field(&file_manager::io_task::ProgressStatus::state,
file_manager::io_task::State::kPaused),
testing::Field(&file_manager::io_task::ProgressStatus::pause_params,
pause_params))));
// FPNM should also get notified to show the notification by this call.
EXPECT_CALL(
*fpnm_,
ShowFilesPolicyNotification(
"swa-file-operation-1",
AllOf(testing::Field(&file_manager::io_task::ProgressStatus::task_id,
task_id),
testing::Field(&file_manager::io_task::ProgressStatus::state,
file_manager::io_task::State::kPaused),
testing::Field(
&file_manager::io_task::ProgressStatus::pause_params,
pause_params))));
EXPECT_TRUE(RunExtensionTest("file_browser/dlp_metadata",
{.custom_arg = "progressPausedTasks"},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiDlpTest,
DlpMetadata_ShowPolicyDialog) {
policy::DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetDlpRulesManager,
base::Unretained(this)));
ASSERT_TRUE(policy::DlpRulesManagerFactory::GetForPrimaryProfile());
EXPECT_CALL(*mock_rules_manager_, IsFilesPolicyEnabled).Times(0);
// We should not get to the point of checking DLP.
EXPECT_CALL(*mock_rules_manager_, IsRestrictedByAnyRule).Times(0);
// Set up FPNM.
policy::FilesPolicyNotificationManagerFactory::GetInstance()
->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetFPNM,
base::Unretained(this)));
// FPNM is created lazily so initialize it before running the test.
ASSERT_TRUE(
policy::FilesPolicyNotificationManagerFactory::GetForBrowserContext(
browser()->profile()));
// Expect only the calls with valid parameters.
testing::InSequence s;
EXPECT_CALL(*fpnm_, ShowDialog(1u, policy::FilesDialogType::kWarning));
EXPECT_CALL(*fpnm_, ShowDialog(2u, policy::FilesDialogType::kError));
EXPECT_TRUE(RunExtensionTest("file_browser/dlp_metadata",
{.custom_arg = "showPolicyDialog"},
{.load_as_component = true}));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiDlpTest,
DlpMetadata_GetDialogCaller) {
policy::DlpRulesManagerFactory::GetInstance()->SetTestingFactory(
browser()->profile(),
base::BindRepeating(&FileManagerPrivateApiDlpTest::SetDlpRulesManager,
base::Unretained(this)));
ASSERT_TRUE(policy::DlpRulesManagerFactory::GetForPrimaryProfile());
policy::DlpFileDestination caller(GURL("https://example.com"));
SelectFileDialogExtensionUserData::SetDialogCallerForTesting(&caller);
EXPECT_TRUE(RunExtensionTest("file_browser/dlp_metadata",
{.custom_arg = "getDialogCaller"},
{.load_as_component = true}));
}