blob: 4acd02606eb223366392752408b09a5c2c791149 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
[email protected]49df6022008-08-27 19:03:432// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
[email protected]5af2edb92008-08-08 20:16:084
[email protected]dea1d7d2012-09-20 16:24:525// Defines base::PathProviderMac which replaces base::PathProviderPosix for Mac
6// in base/path_service.cc.
[email protected]5af2edb92008-08-08 20:16:087
[email protected]699c26c2011-05-26 16:19:018#include <dlfcn.h>
[email protected]880a6d5e2010-11-16 22:25:479#import <Foundation/Foundation.h>
[email protected]b88a291b2009-10-15 01:22:5110#include <mach-o/dyld.h>
avi9b6f42932015-12-26 22:15:1411#include <stdint.h>
[email protected]5af2edb92008-08-08 20:16:0812
[email protected]dea1d7d2012-09-20 16:24:5213#include "base/base_paths.h"
Hans Wennborga47ddf82020-05-05 18:08:0714#include "base/check_op.h"
[email protected]57999812013-02-24 05:40:5215#include "base/files/file_path.h"
[email protected]e3177dd52014-08-13 20:22:1416#include "base/files/file_util.h"
Sergey Ulanovd5ae68e2018-02-07 20:14:2117#include "base/mac/bundle_locations.h"
[email protected]542cbb692011-06-14 19:03:1618#include "base/mac/foundation_util.h"
Hans Wennborga47ddf82020-05-05 18:08:0719#include "base/notreached.h"
[email protected]37088fef2008-08-15 17:32:1020#include "base/path_service.h"
[email protected]251cd6e52013-06-11 13:36:3721#include "base/strings/string_util.h"
wezadb3c21552016-07-14 21:25:2022#include "base/threading/thread_restrictions.h"
[email protected]dea1d7d2012-09-20 16:24:5223#include "build/build_config.h"
[email protected]5af2edb92008-08-08 20:16:0824
[email protected]a6849212010-08-24 21:32:3525namespace {
26
[email protected]aaa6df42013-02-17 19:36:0327void GetNSExecutablePath(base::FilePath* path) {
[email protected]a6849212010-08-24 21:32:3528 DCHECK(path);
29 // Executable path can have relative references ("..") depending on
30 // how the app was launched.
31 uint32_t executable_length = 0;
32 _NSGetExecutablePath(NULL, &executable_length);
[email protected]fdce4782011-11-29 20:06:1833 DCHECK_GT(executable_length, 1u);
[email protected]a6849212010-08-24 21:32:3534 std::string executable_path;
Brett Wilsone3c4d1a2015-07-07 23:38:0935 int rv = _NSGetExecutablePath(
36 base::WriteInto(&executable_path, executable_length),
37 &executable_length);
[email protected]a6849212010-08-24 21:32:3538 DCHECK_EQ(rv, 0);
[email protected]40fd7052013-08-06 13:30:2539
40 // _NSGetExecutablePath may return paths containing ./ or ../ which makes
41 // FilePath::DirName() work incorrectly, convert it to absolute path so that
David Dorwinc694f722021-10-29 22:46:5942 // paths such as DIR_SRC_TEST_DATA_ROOT can work, since we expect absolute
43 // paths to be returned here.
wezadb3c21552016-07-14 21:25:2044 // TODO(bauerb): http://crbug.com/259796, http://crbug.com/373477
45 base::ThreadRestrictions::ScopedAllowIO allow_io;
[email protected]40fd7052013-08-06 13:30:2546 *path = base::MakeAbsoluteFilePath(base::FilePath(executable_path));
[email protected]a6849212010-08-24 21:32:3547}
48
[email protected]699c26c2011-05-26 16:19:0149// Returns true if the module for |address| is found. |path| will contain
50// the path to the module. Note that |path| may not be absolute.
Daniel Cheng4455c9842022-01-13 23:26:3751[[nodiscard]] bool GetModulePathForAddress(base::FilePath* path,
52 const void* address);
[email protected]699c26c2011-05-26 16:19:0153
[email protected]aaa6df42013-02-17 19:36:0354bool GetModulePathForAddress(base::FilePath* path, const void* address) {
[email protected]699c26c2011-05-26 16:19:0155 Dl_info info;
56 if (dladdr(address, &info) == 0)
57 return false;
[email protected]aaa6df42013-02-17 19:36:0358 *path = base::FilePath(info.dli_fname);
[email protected]699c26c2011-05-26 16:19:0159 return true;
60}
61
[email protected]a6849212010-08-24 21:32:3562} // namespace
63
[email protected]5af2edb92008-08-08 20:16:0864namespace base {
65
[email protected]aaa6df42013-02-17 19:36:0366bool PathProviderMac(int key, base::FilePath* result) {
[email protected]5af2edb92008-08-08 20:16:0867 switch (key) {
68 case base::FILE_EXE:
[email protected]fdce4782011-11-29 20:06:1869 GetNSExecutablePath(result);
70 return true;
[email protected]699c26c2011-05-26 16:19:0171 case base::FILE_MODULE:
72 return GetModulePathForAddress(result,
73 reinterpret_cast<const void*>(&base::PathProviderMac));
[email protected]8495af32012-08-01 00:29:1574 case base::DIR_APP_DATA: {
75 bool success = base::mac::GetUserDirectory(NSApplicationSupportDirectory,
76 result);
Xiaohan Wang38e4ebb2022-01-19 06:57:4377#if BUILDFLAG(IS_IOS)
[email protected]8495af32012-08-01 00:29:1578 // On IOS, this directory does not exist unless it is created explicitly.
[email protected]7567484142013-07-11 17:36:0779 if (success && !base::PathExists(*result))
[email protected]426d1c92013-12-03 20:08:5480 success = base::CreateDirectory(*result);
Xiaohan Wang38e4ebb2022-01-19 06:57:4381#endif // BUILDFLAG(IS_IOS)
[email protected]8495af32012-08-01 00:29:1582 return success;
83 }
David Dorwinc694f722021-10-29 22:46:5984 case base::DIR_SRC_TEST_DATA_ROOT:
Xiaohan Wang38e4ebb2022-01-19 06:57:4385#if BUILDFLAG(IS_IOS)
Sylvain Defresnebcf96e42020-04-15 13:20:3286 // On iOS, there is no access to source root, however, the necessary
87 // resources are packaged into the test as assets.
88 return PathService::Get(base::DIR_ASSETS, result);
89#else
[email protected]7fac8882010-11-15 19:52:5290 // Go through PathService to catch overrides.
[email protected]b266ffea2011-04-12 06:07:2591 if (!PathService::Get(base::FILE_EXE, result))
92 return false;
93
94 // Start with the executable's directory.
95 *result = result->DirName();
[email protected]da19703b2012-07-17 14:15:3496
[email protected]b266ffea2011-04-12 06:07:2597 if (base::mac::AmIBundled()) {
98 // The bundled app executables (Chromium, TestShell, etc) live five
99 // levels down, eg:
100 // src/xcodebuild/{Debug|Release}/Chromium.app/Contents/MacOS/Chromium
101 *result = result->DirName().DirName().DirName().DirName().DirName();
102 } else {
103 // Unit tests execute two levels deep from the source root, eg:
104 // src/xcodebuild/{Debug|Release}/base_unittests
105 *result = result->DirName().DirName();
[email protected]d480bc82009-04-22 18:35:10106 }
[email protected]e2ac70002008-12-09 14:58:13107 return true;
Xiaohan Wang38e4ebb2022-01-19 06:57:43108#endif // BUILDFLAG(IS_IOS)
[email protected]dea1d7d2012-09-20 16:24:52109 case base::DIR_USER_DESKTOP:
Xiaohan Wang38e4ebb2022-01-19 06:57:43110#if BUILDFLAG(IS_IOS)
[email protected]ce576fe22012-09-25 18:16:25111 // iOS does not have desktop directories.
112 NOTIMPLEMENTED();
113 return false;
114#else
[email protected]dea1d7d2012-09-20 16:24:52115 return base::mac::GetUserDirectory(NSDesktopDirectory, result);
[email protected]ce576fe22012-09-25 18:16:25116#endif
Sergey Ulanovd5ae68e2018-02-07 20:14:21117 case base::DIR_ASSETS:
Mike Pinkerton798135812022-05-19 17:31:37118#if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_MACCATALYST)
Sylvain Defresnebcf96e42020-04-15 13:20:32119 // On iOS, the assets are located next to the module binary.
Wez15946df2019-04-30 21:42:09120 return PathService::Get(base::DIR_MODULE, result);
121#else
Sergey Ulanovd5ae68e2018-02-07 20:14:21122 if (!base::mac::AmIBundled()) {
123 return PathService::Get(base::DIR_MODULE, result);
124 }
Mike Pinkerton798135812022-05-19 17:31:37125#if BUILDFLAG(IS_IOS_MACCATALYST)
Mike Pinkerton7226a9f2022-05-18 18:27:35126 *result = base::mac::MainBundlePath()
127 .Append(FILE_PATH_LITERAL("Contents"))
128 .Append(FILE_PATH_LITERAL("Resources"));
129#else
Sergey Ulanovd5ae68e2018-02-07 20:14:21130 *result = base::mac::FrameworkBundlePath().Append(
131 FILE_PATH_LITERAL("Resources"));
Mike Pinkerton798135812022-05-19 17:31:37132#endif // BUILDFLAG(IS_IOS_MACCATALYST)
Sergey Ulanovd5ae68e2018-02-07 20:14:21133 return true;
Mike Pinkerton798135812022-05-19 17:31:37134#endif // BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_MACCATALYST)
[email protected]dea1d7d2012-09-20 16:24:52135 case base::DIR_CACHE:
136 return base::mac::GetUserDirectory(NSCachesDirectory, result);
[email protected]5af2edb92008-08-08 20:16:08137 default:
138 return false;
139 }
[email protected]5af2edb92008-08-08 20:16:08140}
141
142} // namespace base