| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Defines base::PathProviderMac which replaces base::PathProviderPosix for Mac | |
| 6 // in base/path_service.cc. | |
| 7 | |
| 8 #include <dlfcn.h> | |
| 9 #import <Foundation/Foundation.h> | |
| 10 #include <mach-o/dyld.h> | |
| 11 | |
| 12 #include "base/base_paths.h" | |
| 13 #include "base/compiler_specific.h" | |
| 14 #include "base/files/file_path.h" | |
| 15 #include "base/files/file_util.h" | |
| 16 #include "base/logging.h" | |
| 17 #include "base/mac/foundation_util.h" | |
| 18 #include "base/path_service.h" | |
| 19 #include "base/strings/string_util.h" | |
| 20 #include "build/build_config.h" | |
| 21 | |
| 22 namespace { | |
| 23 | |
| 24 void GetNSExecutablePath(base::FilePath* path) { | |
| 25 DCHECK(path); | |
| 26 // Executable path can have relative references ("..") depending on | |
| 27 // how the app was launched. | |
| 28 uint32_t executable_length = 0; | |
| 29 _NSGetExecutablePath(NULL, &executable_length); | |
| 30 DCHECK_GT(executable_length, 1u); | |
| 31 std::string executable_path; | |
| 32 int rv = _NSGetExecutablePath( | |
| 33 base::WriteInto(&executable_path, executable_length), &executable_length); | |
| 34 DCHECK_EQ(rv, 0); | |
| 35 | |
| 36 // _NSGetExecutablePath may return paths containing ./ or ../ which makes | |
| 37 // FilePath::DirName() work incorrectly, convert it to absolute path so that | |
| 38 // paths such as DIR_SOURCE_ROOT can work, since we expect absolute paths to | |
| 39 // be returned here. | |
| 40 *path = base::MakeAbsoluteFilePath(base::FilePath(executable_path)); | |
| 41 } | |
| 42 | |
| 43 // Returns true if the module for |address| is found. |path| will contain | |
| 44 // the path to the module. Note that |path| may not be absolute. | |
| 45 bool GetModulePathForAddress(base::FilePath* path, | |
| 46 const void* address) WARN_UNUSED_RESULT; | |
| 47 | |
| 48 bool GetModulePathForAddress(base::FilePath* path, const void* address) { | |
| 49 Dl_info info; | |
| 50 if (dladdr(address, &info) == 0) | |
| 51 return false; | |
| 52 *path = base::FilePath(info.dli_fname); | |
| 53 return true; | |
| 54 } | |
| 55 | |
| 56 } // namespace | |
| 57 | |
| 58 namespace base { | |
| 59 | |
| 60 bool PathProviderMac(int key, base::FilePath* result) { | |
| 61 switch (key) { | |
| 62 case base::FILE_EXE: | |
| 63 GetNSExecutablePath(result); | |
| 64 return true; | |
| 65 case base::FILE_MODULE: | |
| 66 return GetModulePathForAddress(result, | |
| 67 reinterpret_cast<const void*>(&base::PathProviderMac)); | |
| 68 case base::DIR_APP_DATA: { | |
| 69 bool success = base::mac::GetUserDirectory(NSApplicationSupportDirectory, | |
| 70 result); | |
| 71 #if defined(OS_IOS) | |
| 72 // On IOS, this directory does not exist unless it is created explicitly. | |
| 73 if (success && !base::PathExists(*result)) | |
| 74 success = base::CreateDirectory(*result); | |
| 75 #endif // defined(OS_IOS) | |
| 76 return success; | |
| 77 } | |
| 78 case base::DIR_SOURCE_ROOT: | |
| 79 // Go through PathService to catch overrides. | |
| 80 if (!PathService::Get(base::FILE_EXE, result)) | |
| 81 return false; | |
| 82 | |
| 83 // Start with the executable's directory. | |
| 84 *result = result->DirName(); | |
| 85 | |
| 86 #if !defined(OS_IOS) | |
| 87 if (base::mac::AmIBundled()) { | |
| 88 // The bundled app executables (Chromium, TestShell, etc) live five | |
| 89 // levels down, eg: | |
| 90 // src/xcodebuild/{Debug|Release}/Chromium.app/Contents/MacOS/Chromium | |
| 91 *result = result->DirName().DirName().DirName().DirName().DirName(); | |
| 92 } else { | |
| 93 // Unit tests execute two levels deep from the source root, eg: | |
| 94 // src/xcodebuild/{Debug|Release}/base_unittests | |
| 95 *result = result->DirName().DirName(); | |
| 96 } | |
| 97 #endif | |
| 98 return true; | |
| 99 case base::DIR_USER_DESKTOP: | |
| 100 #if defined(OS_IOS) | |
| 101 // iOS does not have desktop directories. | |
| 102 NOTIMPLEMENTED(); | |
| 103 return false; | |
| 104 #else | |
| 105 return base::mac::GetUserDirectory(NSDesktopDirectory, result); | |
| 106 #endif | |
| 107 case base::DIR_CACHE: | |
| 108 return base::mac::GetUserDirectory(NSCachesDirectory, result); | |
| 109 default: | |
| 110 return false; | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 } // namespace base | |
| OLD | NEW |