Commit 45ec05e7 authored by Luciano Pacheco's avatar Luciano Pacheco Committed by Commit Bot

Add feature flag MyFilesVolume and change path_util to use it

Add feature flag MyFilesVolume that when it's enabled the MyFiles folder
will be an actual volume and Downloads will be just a plain folder
inside it.

Change GetDownloadsFolderForProfile to return
<cryptohome>/MyFiles/Downloads when the flag is active.

Add a new function GetMyFilesFolderForProfile which returns the correct
folder to be used as volume root, when the flag is disable it returns
the current value, by calling GetDownloadsFolderForProfile, which
returns <cryptohome>/Downloads. When the flag is active it returns
<cryptohome>/MyFiles.

Change GetPathDisplayTextForSettings to recognize the
<cryptohome>/MyFiles/Downloads pattern, for now it will return just
Downloads.

This is an initial work, follow up CLs wil change the rest of code base
to use either GetDownloadsFolderForProfile (when the code wants the
actual downloads folder) or GetMyFilesFolderForProfile when the code
wants the volume root, previously these 2 situations were the same path;
when the new flag is enabled they're different and depending on the use
case we might have to change to GetMyFilesFolderForProfile.

Bug: 873539

Change-Id: I7d01bc5370072ba574a6761d4a54d43d4b62ff6e
Reviewed-on: https://chromium-review.googlesource.com/c/1298824
Commit-Queue: Luciano Pacheco <lucmult@chromium.org>
Reviewed-by: default avatarSam McNally <sammc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#602979}
parent 2bd4e9c4
...@@ -40,6 +40,7 @@ namespace util { ...@@ -40,6 +40,7 @@ namespace util {
namespace { namespace {
constexpr char kDownloadsFolderName[] = "Downloads"; constexpr char kDownloadsFolderName[] = "Downloads";
constexpr char kMyFilesFolderName[] = "MyFiles";
constexpr char kGoogleDriveDisplayName[] = "Google Drive"; constexpr char kGoogleDriveDisplayName[] = "Google Drive";
constexpr char kMyDriveDisplayName[] = "My Drive"; constexpr char kMyDriveDisplayName[] = "My Drive";
constexpr char kTeamDrivesDisplayName[] = "Team Drives"; constexpr char kTeamDrivesDisplayName[] = "Team Drives";
...@@ -82,6 +83,22 @@ void OnAllContentUrlsResolved(ConvertToContentUrlsCallback callback, ...@@ -82,6 +83,22 @@ void OnAllContentUrlsResolved(ConvertToContentUrlsCallback callback,
std::move(callback).Run(*urls); std::move(callback).Run(*urls);
} }
// On non-ChromeOS system (test+development), the primary profile uses
// $HOME/Downloads for ease access to local files for debugging.
bool ShouldMountPrimaryUserDownloads(Profile* profile) {
if (!base::SysInfo::IsRunningOnChromeOS() &&
user_manager::UserManager::IsInitialized()) {
const user_manager::User* const user =
chromeos::ProfileHelper::Get()->GetUserByProfile(
profile->GetOriginalProfile());
const user_manager::User* const primary_user =
user_manager::UserManager::Get()->GetPrimaryUser();
return user == primary_user;
}
return false;
}
} // namespace } // namespace
const base::FilePath::CharType kRemovableMediaPath[] = const base::FilePath::CharType kRemovableMediaPath[] =
...@@ -100,23 +117,44 @@ base::FilePath GetDownloadsFolderForProfile(Profile* profile) { ...@@ -100,23 +117,44 @@ base::FilePath GetDownloadsFolderForProfile(Profile* profile) {
if (mount_points->GetRegisteredPath(mount_point_name, &path)) if (mount_points->GetRegisteredPath(mount_point_name, &path))
return path; return path;
// On non-ChromeOS system (test+development), the primary profile uses // Return $HOME/Downloads as Download folder.
// $HOME/Downloads for ease for accessing local files for debugging. if (ShouldMountPrimaryUserDownloads(profile))
if (!base::SysInfo::IsRunningOnChromeOS() && return DownloadPrefs::GetDefaultDownloadDirectory();
user_manager::UserManager::IsInitialized()) {
const user_manager::User* const user = // Return <cryptohome>/MyFiles/Downloads if it feature is enabled.
chromeos::ProfileHelper::Get()->GetUserByProfile( if (base::FeatureList::IsEnabled(chromeos::features::kMyFilesVolume)) {
profile->GetOriginalProfile()); return profile->GetPath()
const user_manager::User* const primary_user = .AppendASCII(kMyFilesFolderName)
user_manager::UserManager::Get()->GetPrimaryUser(); .AppendASCII(kDownloadsFolderName);
if (user == primary_user)
return DownloadPrefs::GetDefaultDownloadDirectory();
} }
// Return <cryptohome>/Downloads. // Return <cryptohome>/Downloads.
return profile->GetPath().AppendASCII(kDownloadsFolderName); return profile->GetPath().AppendASCII(kDownloadsFolderName);
} }
base::FilePath GetMyFilesFolderForProfile(Profile* profile) {
// When MyFilesVolume feature is disabled this should behave just like
// GetDownloadsFolderForProfile.
if (!base::FeatureList::IsEnabled(chromeos::features::kMyFilesVolume))
return GetDownloadsFolderForProfile(profile);
// Check if FilesApp has a registered path already. This happens for tests.
const std::string mount_point_name =
util::GetDownloadsMountPointName(profile);
storage::ExternalMountPoints* const mount_points =
storage::ExternalMountPoints::GetSystemInstance();
base::FilePath path;
if (mount_points->GetRegisteredPath(mount_point_name, &path))
return path;
// Return $HOME/Downloads as MyFiles folder.
if (ShouldMountPrimaryUserDownloads(profile))
return DownloadPrefs::GetDefaultDownloadDirectory();
// Return <cryptohome>/MyFiles.
return profile->GetPath().AppendASCII(kMyFilesFolderName);
}
bool MigratePathFromOldFormat(Profile* profile, bool MigratePathFromOldFormat(Profile* profile,
const base::FilePath& old_path, const base::FilePath& old_path,
base::FilePath* new_path) { base::FilePath* new_path) {
...@@ -366,6 +404,15 @@ std::string GetPathDisplayTextForSettings(Profile* profile, ...@@ -366,6 +404,15 @@ std::string GetPathDisplayTextForSettings(Profile* profile,
profile->GetPath().BaseName().value() + profile->GetPath().BaseName().value() +
"/Downloads", "/Downloads",
kDownloadsFolderName)) { kDownloadsFolderName)) {
} else if (ReplacePrefix(&result,
std::string("/home/chronos/user/") +
kMyFilesFolderName + "/" + kDownloadsFolderName,
kDownloadsFolderName)) {
} else if (ReplacePrefix(&result,
"/home/chronos/" +
profile->GetPath().BaseName().value() + "/" +
kMyFilesFolderName + "/" + kDownloadsFolderName,
kDownloadsFolderName)) {
} else if (drive_integration_service && } else if (drive_integration_service &&
ReplacePrefix(&result, ReplacePrefix(&result,
drive_integration_service->GetMountPointPath() drive_integration_service->GetMountPointPath()
......
...@@ -27,6 +27,9 @@ extern const base::FilePath::CharType kAndroidFilesPath[]; ...@@ -27,6 +27,9 @@ extern const base::FilePath::CharType kAndroidFilesPath[];
// Gets the absolute path for the 'Downloads' folder for the |profile|. // Gets the absolute path for the 'Downloads' folder for the |profile|.
base::FilePath GetDownloadsFolderForProfile(Profile* profile); base::FilePath GetDownloadsFolderForProfile(Profile* profile);
// Gets the absolute path for the 'MyFiles' folder for the |profile|.
base::FilePath GetMyFilesFolderForProfile(Profile* profile);
// Converts |old_path| to |new_path| and returns true, if the old path points // Converts |old_path| to |new_path| and returns true, if the old path points
// to an old location of user folders (in "Downloads" or "Google Drive"). // to an old location of user folders (in "Downloads" or "Google Drive").
// The |profile| argument is used for determining the location of the // The |profile| argument is used for determining the location of the
......
...@@ -47,6 +47,66 @@ const char kLsbRelease[] = ...@@ -47,6 +47,66 @@ const char kLsbRelease[] =
"CHROMEOS_RELEASE_NAME=Chrome OS\n" "CHROMEOS_RELEASE_NAME=Chrome OS\n"
"CHROMEOS_RELEASE_VERSION=1.2.3.4\n"; "CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
TEST(FileManagerPathUtilTest, GetDownloadsFolderForProfile) {
content::TestBrowserThreadBundle thread_bundle;
TestingProfile profile(base::FilePath("/home/chronos/u-0123456789abcdef"));
std::string mount_point_name = GetDownloadsMountPointName(&profile);
EXPECT_EQ("Downloads", mount_point_name);
}
TEST(FileManagerPathUtilTest, GetMyFilesFolderForProfile) {
content::TestBrowserThreadBundle thread_bundle;
base::FilePath profile_path =
base::FilePath("/home/chronos/u-0123456789abcdef");
TestingProfile profile(profile_path);
// When running outside ChromeOS, it should return $HOME/Downloads for both
// MyFiles and Downloads.
EXPECT_EQ(DownloadPrefs::GetDefaultDownloadDirectory(),
GetMyFilesFolderForProfile(&profile));
EXPECT_EQ(DownloadPrefs::GetDefaultDownloadDirectory(),
GetDownloadsFolderForProfile(&profile));
// When running inside ChromeOS, it should return /home/u-{hash}/MyFiles.
chromeos::ScopedSetRunningOnChromeOSForTesting fake_release(kLsbRelease,
base::Time());
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(chromeos::features::kMyFilesVolume);
// When MyFilesVolume feature is disabled it will return the same as
// Downloads.
EXPECT_EQ(GetDownloadsFolderForProfile(&profile),
GetMyFilesFolderForProfile(&profile));
EXPECT_EQ("/home/chronos/u-0123456789abcdef/Downloads",
GetDownloadsFolderForProfile(&profile).value());
}
{
// When MyFilesVolume feature is enabled Downloads path is inside MyFiles.
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(chromeos::features::kMyFilesVolume);
base::FilePath myfiles_path = profile_path.AppendASCII("MyFiles");
base::FilePath myfiles_downloads_path =
myfiles_path.AppendASCII("Downloads");
EXPECT_EQ("/home/chronos/u-0123456789abcdef/MyFiles",
GetMyFilesFolderForProfile(&profile).value());
EXPECT_EQ("/home/chronos/u-0123456789abcdef/MyFiles/Downloads",
GetDownloadsFolderForProfile(&profile).value());
// Mount the volume to test the return from mount_points.
storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
GetDownloadsMountPointName(&profile),
storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(),
profile_path.Append("MyFiles"));
// Still the same: /home/u-{hash}/MyFiles.
EXPECT_EQ("/home/chronos/u-0123456789abcdef/MyFiles",
GetMyFilesFolderForProfile(&profile).value());
}
}
TEST(FileManagerPathUtilTest, GetPathDisplayTextForSettings) { TEST(FileManagerPathUtilTest, GetPathDisplayTextForSettings) {
content::TestBrowserThreadBundle thread_bundle; content::TestBrowserThreadBundle thread_bundle;
content::TestServiceManagerContext service_manager_context; content::TestServiceManagerContext service_manager_context;
...@@ -58,6 +118,14 @@ TEST(FileManagerPathUtilTest, GetPathDisplayTextForSettings) { ...@@ -58,6 +118,14 @@ TEST(FileManagerPathUtilTest, GetPathDisplayTextForSettings) {
EXPECT_EQ("Downloads", EXPECT_EQ("Downloads",
GetPathDisplayTextForSettings( GetPathDisplayTextForSettings(
&profile, "/home/chronos/u-0123456789abcdef/Downloads")); &profile, "/home/chronos/u-0123456789abcdef/Downloads"));
EXPECT_EQ("Downloads", GetPathDisplayTextForSettings(
&profile, "/home/chronos/user/MyFiles/Downloads"));
EXPECT_EQ(
"Downloads",
GetPathDisplayTextForSettings(
&profile, "/home/chronos/u-0123456789abcdef/MyFiles/Downloads"));
EXPECT_EQ("Play files \u203a foo \u203a bar", EXPECT_EQ("Play files \u203a foo \u203a bar",
GetPathDisplayTextForSettings( GetPathDisplayTextForSettings(
&profile, "/run/arc/sdcard/write/emulated/0/foo/bar")); &profile, "/run/arc/sdcard/write/emulated/0/foo/bar"));
......
...@@ -23,6 +23,11 @@ const base::Feature kChromeVoxArcSupport{"ChromeVoxArcSupport", ...@@ -23,6 +23,11 @@ const base::Feature kChromeVoxArcSupport{"ChromeVoxArcSupport",
// If enabled, DriveFS will be used for Drive sync. // If enabled, DriveFS will be used for Drive sync.
const base::Feature kDriveFs{"DriveFS", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kDriveFs{"DriveFS", base::FEATURE_DISABLED_BY_DEFAULT};
// If enabled, MyFiles will be a root/volume and user can create other
// sub-folders and files in addition to the Downloads folder inside MyFiles.
const base::Feature kMyFilesVolume{"MyFilesVolume",
base::FEATURE_DISABLED_BY_DEFAULT};
// If enabled, the Chrome OS Settings UI will include a menu for the unified // If enabled, the Chrome OS Settings UI will include a menu for the unified
// MultiDevice settings. // MultiDevice settings.
const base::Feature kEnableUnifiedMultiDeviceSettings{ const base::Feature kEnableUnifiedMultiDeviceSettings{
......
...@@ -19,6 +19,7 @@ CHROMEOS_EXPORT extern const base::Feature kAndroidMessagesIntegration; ...@@ -19,6 +19,7 @@ CHROMEOS_EXPORT extern const base::Feature kAndroidMessagesIntegration;
CHROMEOS_EXPORT extern const base::Feature kAndroidMessagesProdEndpoint; CHROMEOS_EXPORT extern const base::Feature kAndroidMessagesProdEndpoint;
CHROMEOS_EXPORT extern const base::Feature kChromeVoxArcSupport; CHROMEOS_EXPORT extern const base::Feature kChromeVoxArcSupport;
CHROMEOS_EXPORT extern const base::Feature kDriveFs; CHROMEOS_EXPORT extern const base::Feature kDriveFs;
CHROMEOS_EXPORT extern const base::Feature kMyFilesVolume;
CHROMEOS_EXPORT extern const base::Feature kEnableUnifiedMultiDeviceSettings; CHROMEOS_EXPORT extern const base::Feature kEnableUnifiedMultiDeviceSettings;
CHROMEOS_EXPORT extern const base::Feature kEnableUnifiedMultiDeviceSetup; CHROMEOS_EXPORT extern const base::Feature kEnableUnifiedMultiDeviceSetup;
CHROMEOS_EXPORT extern const base::Feature kImeServiceConnectable; CHROMEOS_EXPORT extern const base::Feature kImeServiceConnectable;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment