feat: Use DIR_ASSETS path to locate resource bundles (#47950)

* feat: Use DIR_ASSETS path to locate resource bundles

Co-authored-by: Will Anderson <andersonw@dropbox.com>

* Use DIR_ASSETS for calculating ASAR relative paths

Co-authored-by: Will Anderson <andersonw@dropbox.com>

* Add test to verify 'assets' matches parent dir of 'exe'

Co-authored-by: Will Anderson <andersonw@dropbox.com>

* Add Mac-specific test for assets path (but it is failing)

Co-authored-by: Will Anderson <andersonw@dropbox.com>

* test: Update app.getPath('assets') to expect an exception on Mac

Co-authored-by: Will Anderson <andersonw@dropbox.com>

* docs: Update docs for 'assets' path to indicate that it's only available on Windows + Linux

Co-authored-by: Will Anderson <andersonw@dropbox.com>

* fix: Don't define 'assets' mapping on macOS

Co-authored-by: Will Anderson <andersonw@dropbox.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Will Anderson <andersonw@dropbox.com>
This commit is contained in:
trop[bot] 2025-08-06 19:40:11 +02:00 committed by GitHub
commit 433f9f5e8c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 27 additions and 10 deletions

View file

@ -602,6 +602,7 @@ Returns `string` - The current application directory.
* `%APPDATA%` on Windows * `%APPDATA%` on Windows
* `$XDG_CONFIG_HOME` or `~/.config` on Linux * `$XDG_CONFIG_HOME` or `~/.config` on Linux
* `~/Library/Application Support` on macOS * `~/Library/Application Support` on macOS
* `assets` The directory where app assets such as `resources.pak` are stored. By default this is the same as the folder containing the `exe` path. Available on Windows and Linux only.
* `userData` The directory for storing your app's configuration files, which * `userData` The directory for storing your app's configuration files, which
by default is the `appData` directory appended with your app's name. By by default is the `appData` directory appended with your app's name. By
convention files storing user data should be written to this directory, and convention files storing user data should be written to this directory, and
@ -616,7 +617,7 @@ Returns `string` - The current application directory.
directory. directory.
* `temp` Temporary directory. * `temp` Temporary directory.
* `exe` The current executable file. * `exe` The current executable file.
* `module` The `libchromiumcontent` library. * `module` The location of the Chromium module. By default this is synonymous with `exe`.
* `desktop` The current user's Desktop directory. * `desktop` The current user's Desktop directory.
* `documents` Directory for a user's "My Documents". * `documents` Directory for a user's "My Documents".
* `downloads` Directory for a user's downloads. * `downloads` Directory for a user's downloads.

View file

@ -219,7 +219,7 @@ std::string LoadResourceBundle(const std::string& locale) {
pak_dir = pak_dir =
base::apple::FrameworkBundlePath().Append(FILE_PATH_LITERAL("Resources")); base::apple::FrameworkBundlePath().Append(FILE_PATH_LITERAL("Resources"));
#else #else
base::PathService::Get(base::DIR_MODULE, &pak_dir); base::PathService::Get(base::DIR_ASSETS, &pak_dir);
#endif #endif
std::string loaded_locale = ui::ResourceBundle::InitSharedInstanceWithLocale( std::string loaded_locale = ui::ResourceBundle::InitSharedInstanceWithLocale(

View file

@ -383,6 +383,9 @@ int GetPathConstant(std::string_view name) {
// clang-format off // clang-format off
constexpr auto Lookup = base::MakeFixedFlatMap<std::string_view, int>({ constexpr auto Lookup = base::MakeFixedFlatMap<std::string_view, int>({
{"appData", DIR_APP_DATA}, {"appData", DIR_APP_DATA},
#if !BUILDFLAG(IS_MAC)
{"assets", base::DIR_ASSETS},
#endif
#if BUILDFLAG(IS_POSIX) #if BUILDFLAG(IS_POSIX)
{"cache", base::DIR_CACHE}, {"cache", base::DIR_CACHE},
#else #else

View file

@ -26,13 +26,13 @@ const wchar_t kIntegrityCheckResourceType[] = L"Integrity";
const wchar_t kIntegrityCheckResourceItem[] = L"ElectronAsar"; const wchar_t kIntegrityCheckResourceItem[] = L"ElectronAsar";
std::optional<base::FilePath> Archive::RelativePath() const { std::optional<base::FilePath> Archive::RelativePath() const {
base::FilePath exe_path; base::FilePath assets_dir;
if (!base::PathService::Get(base::FILE_EXE, &exe_path)) { if (!base::PathService::Get(base::DIR_ASSETS, &assets_dir)) {
LOG(FATAL) << "Couldn't get exe file path"; LOG(FATAL) << "Couldn't get assets directory path";
} }
base::FilePath relative_path; base::FilePath relative_path;
if (!exe_path.DirName().AppendRelativePath(path_, &relative_path)) { if (!assets_dir.AppendRelativePath(path_, &relative_path)) {
return std::nullopt; return std::nullopt;
} }

View file

@ -456,11 +456,10 @@ base::FilePath GetResourcesPath() {
#if BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_MAC)
return MainApplicationBundlePath().Append("Contents").Append("Resources"); return MainApplicationBundlePath().Append("Contents").Append("Resources");
#else #else
auto* command_line = base::CommandLine::ForCurrentProcess(); base::FilePath assets_path;
base::FilePath exec_path(command_line->GetProgram()); base::PathService::Get(base::DIR_ASSETS, &assets_path);
base::PathService::Get(base::FILE_EXE, &exec_path);
return exec_path.DirName().Append(FILE_PATH_LITERAL("resources")); return assets_path.Append(FILE_PATH_LITERAL("resources"));
#endif #endif
} }
} // namespace } // namespace

View file

@ -1109,6 +1109,20 @@ describe('app module', () => {
expect(paths).to.deep.equal([true, true, true]); expect(paths).to.deep.equal([true, true, true]);
}); });
if (process.platform === 'darwin') {
it('throws an error when trying to get the assets path on macOS', () => {
expect(() => {
app.getPath('assets' as any);
}).to.throw(/Failed to get 'assets' path/);
});
} else {
it('returns an assets path that is identical to the module path', () => {
const assetsPath = app.getPath('assets');
expect(fs.existsSync(assetsPath)).to.be.true();
expect(assetsPath).to.equal(path.dirname(app.getPath('module')));
});
}
it('throws an error when the name is invalid', () => { it('throws an error when the name is invalid', () => {
expect(() => { expect(() => {
app.getPath('does-not-exist' as any); app.getPath('does-not-exist' as any);