Commit bd1a5d50 authored by James Cook's avatar James Cook Committed by Commit Bot

lacros: Fix default download and documents paths

Prior to this CL, files downloaded in Lacros would "disappear" -- they
would not show up in the file manager. The downloads code would choose
its default directory using the Chrome for Linux path provider, which
does not know about Chrome OS paths, and the files would end up in a
directory the file manager can't navigate to.

Add chrome_paths_lacros.cc to supply the correct paths.

Because Lacros does not support Chrome OS multi-signin, we make the
decision that lacros-chrome does not need to know about the under-the-
hood /home/chronos/u-{hash} multi-signin profile directories. It uses
the hard-linked /home/chronos/user path for the system primary profile.
This avoids exposing knowledge of the hash to Lacros.

Bug: 1139082
Change-Id: I8836760632fd9a1a8f9d49d7f03f1e6f6dfb0841
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2500278Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: James Cook <jamescook@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821426}
parent b2e824a0
...@@ -90,16 +90,15 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) { ...@@ -90,16 +90,15 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
} }
base::FilePath GetUserDataDir() { base::FilePath GetUserDataDir() {
base::FilePath base_path;
if (base::SysInfo::IsRunningOnChromeOS()) { if (base::SysInfo::IsRunningOnChromeOS()) {
// NOTE: On device this function is privacy/security sensitive. The // NOTE: On device this function is privacy/security sensitive. The
// directory must be inside the encrypted user partition. // directory must be inside the encrypted user partition.
base_path = base::FilePath("/home/chronos/user"); return base::FilePath(crosapi::kLacrosUserDataPath);
} else {
// For developers on Linux desktop, put the directory under the developer's
// specified --user-data-dir.
base::PathService::Get(chrome::DIR_USER_DATA, &base_path);
} }
// For developers on Linux desktop, put the directory under the developer's
// specified --user-data-dir.
base::FilePath base_path;
base::PathService::Get(chrome::DIR_USER_DATA, &base_path);
return base_path.Append("lacros"); return base_path.Append("lacros");
} }
......
...@@ -4,8 +4,11 @@ ...@@ -4,8 +4,11 @@
#include "chrome/browser/chromeos/crosapi/file_manager_ash.h" #include "chrome/browser/chromeos/crosapi/file_manager_ash.h"
#include "base/files/file_path.h"
#include "chrome/browser/chromeos/file_manager/path_util.h"
#include "chrome/browser/platform_util.h" #include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "chromeos/crosapi/cpp/crosapi_constants.h"
namespace crosapi { namespace crosapi {
...@@ -16,10 +19,17 @@ FileManagerAsh::FileManagerAsh( ...@@ -16,10 +19,17 @@ FileManagerAsh::FileManagerAsh(
FileManagerAsh::~FileManagerAsh() = default; FileManagerAsh::~FileManagerAsh() = default;
void FileManagerAsh::ShowItemInFolder(const base::FilePath& path) { void FileManagerAsh::ShowItemInFolder(const base::FilePath& path) {
Profile* primary_profile = ProfileManager::GetPrimaryUserProfile();
// Lacros does not support multi-signin. Lacros uses /home/chronos/user as the
// base for all system-level directories but the file manager expects the raw
// profile path with the /home/chronos/u-{hash} prefix. Clean up the path.
base::FilePath final_path = file_manager::util::ReplacePathPrefix(
path, base::FilePath(crosapi::kHomeChronosUserPath),
primary_profile->GetPath());
// Use platform_util instead of calling directly into file manager code // Use platform_util instead of calling directly into file manager code
// because platform_util_ash.cc handles showing error dialogs for files and // because platform_util_ash.cc handles showing error dialogs for files and
// paths that cannot be opened. // paths that cannot be opened.
platform_util::ShowItemInFolder(ProfileManager::GetActiveUserProfile(), path); platform_util::ShowItemInFolder(primary_profile, final_path);
} }
} // namespace crosapi } // namespace crosapi
...@@ -762,5 +762,16 @@ bool ExtractMountNameFileSystemNameFullPath(const base::FilePath& absolute_path, ...@@ -762,5 +762,16 @@ bool ExtractMountNameFileSystemNameFullPath(const base::FilePath& absolute_path,
return true; return true;
} }
base::FilePath ReplacePathPrefix(const base::FilePath& input,
const base::FilePath& old_prefix,
const base::FilePath& new_prefix) {
if (old_prefix.IsParent(input)) {
base::FilePath output = new_prefix;
old_prefix.AppendRelativePath(input, &output);
return output;
}
return input;
}
} // namespace util } // namespace util
} // namespace file_manager } // namespace file_manager
...@@ -154,6 +154,15 @@ bool ExtractMountNameFileSystemNameFullPath(const base::FilePath& absolute_path, ...@@ -154,6 +154,15 @@ bool ExtractMountNameFileSystemNameFullPath(const base::FilePath& absolute_path,
std::string* mount_name, std::string* mount_name,
std::string* file_system_name, std::string* file_system_name,
std::string* full_path); std::string* full_path);
// Convenience wrapper around the FilePath::AppendRelativePath() function.
// For |input| "/foo/bar" and |old_prefix| "/foo" and |new_prefix| "/baz",
// returns "/baz/bar". If |input| does not start with |old_prefix|,
// returns |input|.
base::FilePath ReplacePathPrefix(const base::FilePath& input,
const base::FilePath& old_prefix,
const base::FilePath& new_prefix);
} // namespace util } // namespace util
} // namespace file_manager } // namespace file_manager
......
...@@ -987,6 +987,22 @@ TEST_F(FileManagerPathUtilConvertUrlTest, ConvertToContentUrls_MultipleUrls) { ...@@ -987,6 +987,22 @@ TEST_F(FileManagerPathUtilConvertUrlTest, ConvertToContentUrls_MultipleUrls) {
run_loop.Run(); run_loop.Run();
} }
TEST_F(FileManagerPathUtilTest, ReplacePathPrefixDoesMatch) {
base::FilePath path =
ReplacePathPrefix(base::FilePath("/home/chronos/user/foo.txt"),
base::FilePath("/home/chronos/user"),
base::FilePath("/home/chronos/u-0123456789abcdef"));
EXPECT_EQ(base::FilePath("/home/chronos/u-0123456789abcdef/foo.txt"), path);
}
TEST_F(FileManagerPathUtilTest, ReplacePathPrefixDoesNotMatch) {
base::FilePath path =
ReplacePathPrefix(base::FilePath("/media/removable/a/b/c/foo.txt"),
base::FilePath("/home/chronos/user"),
base::FilePath("/home/chronos/u-0123456789abcdef"));
EXPECT_EQ(base::FilePath("/media/removable/a/b/c/foo.txt"), path);
}
} // namespace } // namespace
} // namespace util } // namespace util
} // namespace file_manager } // namespace file_manager
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import("//build/buildflag_header.gni") import("//build/buildflag_header.gni")
import("//build/config/chrome_build.gni") # For branding_file_path. import("//build/config/chrome_build.gni") # For branding_file_path.
import("//build/config/chromeos/ui_mode.gni")
import("//build/util/process_version.gni") import("//build/util/process_version.gni")
import("//chrome/browser/downgrade/buildflags.gni") import("//chrome/browser/downgrade/buildflags.gni")
import("//chrome/common/features.gni") import("//chrome/common/features.gni")
...@@ -630,7 +631,10 @@ static_library("constants") { ...@@ -630,7 +631,10 @@ static_library("constants") {
# implemented in //ui/base, so we need that dependency. # implemented in //ui/base, so we need that dependency.
deps += [ "//ui/base" ] deps += [ "//ui/base" ]
} }
if (is_linux || is_chromeos) { if (is_lacros) {
sources += [ "chrome_paths_lacros.cc" ]
deps += [ "//chromeos/crosapi/cpp" ]
} else if (is_linux || is_chromeos) {
sources += [ "chrome_paths_linux.cc" ] sources += [ "chrome_paths_linux.cc" ]
} }
if (is_mac) { if (is_mac) {
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/chrome_paths.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/system/sys_info.h"
#include "chromeos/crosapi/cpp/crosapi_constants.h"
namespace chrome {
bool GetDefaultUserDataDirectory(base::FilePath* result) {
if (base::SysInfo::IsRunningOnChromeOS()) {
*result = base::FilePath(crosapi::kLacrosUserDataPath);
} else {
// For developers on Linux desktop, just pick a reasonable default. Most
// developers will pass --user-data-dir and override this value anyway.
*result = base::GetHomeDir().Append(".config").Append("lacros");
}
return true;
}
void GetUserCacheDirectory(const base::FilePath& profile_dir,
base::FilePath* result) {
// Chrome OS doesn't allow special cache overrides like desktop Linux.
*result = profile_dir;
}
bool GetUserDocumentsDirectory(base::FilePath* result) {
if (base::SysInfo::IsRunningOnChromeOS()) {
*result = base::FilePath(crosapi::kMyFilesPath);
} else {
// For developers on Linux desktop, just pick a reasonable default.
*result = base::GetHomeDir().Append("Documents");
}
return true;
}
bool GetUserDownloadsDirectorySafe(base::FilePath* result) {
if (base::SysInfo::IsRunningOnChromeOS()) {
*result = base::FilePath(crosapi::kDefaultDownloadsPath);
} else {
// For developers on Linux desktop, just pick a reasonable default.
*result = base::GetHomeDir().Append("Downloads");
}
return true;
}
bool GetUserDownloadsDirectory(base::FilePath* result) {
return GetUserDownloadsDirectorySafe(result);
}
bool GetUserMusicDirectory(base::FilePath* result) {
// Chrome OS does not support custom media directories.
return false;
}
bool GetUserPicturesDirectory(base::FilePath* result) {
// Chrome OS does not support custom media directories.
return false;
}
bool GetUserVideosDirectory(base::FilePath* result) {
// Chrome OS does not support custom media directories.
return false;
}
bool ProcessNeedsProfileDir(const std::string& process_type) {
// We have no reason to forbid this on Chrome OS as we don't have roaming
// profile troubles there.
return true;
}
} // namespace chrome
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/chrome_paths_internal.h"
#include "base/files/file_path.h"
#include "base/system/sys_info.h"
#include "base/time/time.h"
#include "chromeos/crosapi/cpp/crosapi_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chrome {
namespace {
const char kLsbRelease[] =
"CHROMEOS_RELEASE_NAME=Chrome OS\n"
"CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
// Overrides base::SysInfo::IsRunningOnChromeOS() to return true.
class ScopedIsRunningOnChromeOS {
public:
ScopedIsRunningOnChromeOS() {
base::SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease, base::Time());
}
~ScopedIsRunningOnChromeOS() {
base::SysInfo::SetChromeOSVersionInfoForTest("", base::Time());
}
};
TEST(ChromePaths, UserDataDirectoryIsInsideEncryptedPartition) {
// Force paths to behave like they do on device.
ScopedIsRunningOnChromeOS is_running_on_chromeos;
base::FilePath user_data_dir;
ASSERT_TRUE(GetDefaultUserDataDirectory(&user_data_dir));
// The Lacros user data directory contains profile information, including
// credentials. It must be inside the encrypted system user partition.
base::FilePath home_chronos_user(crosapi::kHomeChronosUserPath);
EXPECT_TRUE(home_chronos_user.IsParent(user_data_dir));
}
} // namespace
} // namespace chrome
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/path_service.h" #include "base/path_service.h"
#include "build/branding_buildflags.h" #include "build/branding_buildflags.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_constants.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -44,8 +45,9 @@ TEST(ChromePaths, UserCacheDir) { ...@@ -44,8 +45,9 @@ TEST(ChromePaths, UserCacheDir) {
#endif #endif
// Verify that a profile in the special platform-specific source // Verify that a profile in the special platform-specific source
// location ends up in the special target location. // location ends up in the special target location. Ignore this assertion on
#if !defined(OS_WIN) // No special behavior on Windows. // platforms that don't use a special cache directory.
#if !defined(OS_WIN) && !BUILDFLAG(IS_LACROS)
GetUserCacheDirectory(test_profile_dir, &cache_dir); GetUserCacheDirectory(test_profile_dir, &cache_dir);
EXPECT_EQ(expected_cache_dir.value(), cache_dir.value()); EXPECT_EQ(expected_cache_dir.value(), cache_dir.value());
#endif #endif
...@@ -61,7 +63,8 @@ TEST(ChromePaths, UserCacheDir) { ...@@ -61,7 +63,8 @@ TEST(ChromePaths, UserCacheDir) {
#endif #endif
} }
#if defined(OS_LINUX) || defined(OS_CHROMEOS) // Chrome OS doesn't use any of the desktop linux configuration.
#if defined(OS_LINUX) && !BUILDFLAG(IS_LACROS) && !BUILDFLAG(IS_ASH)
TEST(ChromePaths, DefaultUserDataDir) { TEST(ChromePaths, DefaultUserDataDir) {
std::unique_ptr<base::Environment> env(base::Environment::Create()); std::unique_ptr<base::Environment> env(base::Environment::Create());
std::string orig_chrome_config_home; std::string orig_chrome_config_home;
...@@ -100,4 +103,14 @@ TEST(ChromePaths, DefaultUserDataDir) { ...@@ -100,4 +103,14 @@ TEST(ChromePaths, DefaultUserDataDir) {
} }
#endif #endif
#if BUILDFLAG(IS_LACROS) || BUILDFLAG(IS_ASH)
TEST(ChromePaths, UserMediaDirectories) {
base::FilePath path;
// Chrome OS does not support custom media directories.
EXPECT_FALSE(GetUserMusicDirectory(&path));
EXPECT_FALSE(GetUserPicturesDirectory(&path));
EXPECT_FALSE(GetUserVideosDirectory(&path));
}
#endif
} // namespace chrome } // namespace chrome
...@@ -4830,7 +4830,10 @@ test("unit_tests") { ...@@ -4830,7 +4830,10 @@ test("unit_tests") {
# TODO(crbug.com/1052397): Rename chromeos_is_browser_only to is_lacros. # TODO(crbug.com/1052397): Rename chromeos_is_browser_only to is_lacros.
if (chromeos_is_browser_only) { if (chromeos_is_browser_only) {
assert(enable_native_notifications) assert(enable_native_notifications)
sources += [ "../browser/notifications/notification_platform_bridge_lacros_unittest.cc" ] sources += [
"../browser/notifications/notification_platform_bridge_lacros_unittest.cc",
"../common/chrome_paths_lacros_unittest.cc",
]
} }
if (is_chromeos) { if (is_chromeos) {
......
...@@ -11,4 +11,20 @@ namespace crosapi { ...@@ -11,4 +11,20 @@ namespace crosapi {
// trailing "." is intentional. // trailing "." is intentional.
const char kLacrosAppIdPrefix[] = "org.chromium.lacros."; const char kLacrosAppIdPrefix[] = "org.chromium.lacros.";
// Path to the ash-side primary user profile directory, which is a hard link to
// a directory in the encrypted user data partition.
const char kHomeChronosUserPath[] = "/home/chronos/user";
// The "MyFiles" directory for the ash-side primary user.
const char kMyFilesPath[] = "/home/chronos/user/MyFiles";
// The "Downloads" directory for the ash-side primary user. Note that the user
// can choose to download files to a different directory, see DownloadPrefs.
const char kDefaultDownloadsPath[] = "/home/chronos/user/MyFiles/Downloads";
// The default user-data-directory for Lacros.
// NOTE: This is security sensitive. The directory must be inside the encrypted
// user data partition.
const char kLacrosUserDataPath[] = "/home/chronos/user/lacros";
} // namespace crosapi } // namespace crosapi
...@@ -11,6 +11,14 @@ namespace crosapi { ...@@ -11,6 +11,14 @@ namespace crosapi {
COMPONENT_EXPORT(CROSAPI) extern const char kLacrosAppIdPrefix[]; COMPONENT_EXPORT(CROSAPI) extern const char kLacrosAppIdPrefix[];
COMPONENT_EXPORT(CROSAPI) extern const char kHomeChronosUserPath[];
COMPONENT_EXPORT(CROSAPI) extern const char kMyFilesPath[];
COMPONENT_EXPORT(CROSAPI) extern const char kDefaultDownloadsPath[];
COMPONENT_EXPORT(CROSAPI) extern const char kLacrosUserDataPath[];
} // namespace crosapi } // namespace crosapi
#endif // CHROMEOS_CROSAPI_CPP_CROSAPI_CONSTANTS_H_ #endif // CHROMEOS_CROSAPI_CPP_CROSAPI_CONSTANTS_H_
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