[go: nahoru, domu]

blob: 112fe01d7f34784c82e4236039bc180c8b58ce8a [file] [log] [blame]
Avi Drissman4a8573c2022-09-09 19:35:541// Copyright 2012 The Chromium Authors
pinkerton@chromium.org409993dec2009-03-03 20:23:042// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
mark@chromium.org927e90a2011-04-19 02:31:425#import <Foundation/Foundation.h>
mark@chromium.org1ce9fe72011-04-19 17:33:006#include <string.h>
7
thakis8b51c0a2016-04-12 19:48:188#include <memory>
mark@chromium.org1ce9fe72011-04-19 17:33:009#include <string>
pinkerton@chromium.org409993dec2009-03-03 20:23:0410
mark@chromium.orge4221ad52009-10-07 16:42:1611#include "base/base_paths.h"
Hans Wennborga47ddf82020-05-05 18:08:0712#include "base/check_op.h"
mark@chromium.org927e90a2011-04-19 02:31:4213#import "base/mac/foundation_util.h"
dchengdb5935f2016-03-26 00:16:2714#include "base/memory/free_deleter.h"
mark@chromium.orge4221ad52009-10-07 16:42:1615#include "base/path_service.h"
Leonard Greyab27aae22021-05-07 14:44:0616#include "base/strings/sys_string_conversions.h"
Nico Weber9116a2f12019-10-07 16:32:1217#include "build/branding_buildflags.h"
avi2729e442015-12-26 05:27:4518#include "build/build_config.h"
mark@chromium.org6a271dba2009-10-08 20:03:5419#include "chrome/common/chrome_constants.h"
thakis8b51c0a2016-04-12 19:48:1820#include "chrome/common/chrome_paths_internal.h"
pinkerton@chromium.org409993dec2009-03-03 20:23:0421
viettrungluu@chromium.orgadf02252010-05-18 22:09:4022namespace {
mark@chromium.org927e90a2011-04-19 02:31:4223
Avi Drissman3f5ffc12023-05-08 21:23:4624// Return an NSBundle* as the internal implementation of
25// chrome::OuterAppBundle(), which should be the only caller.
mark@chromium.org151c4a62011-04-22 04:15:1326NSBundle* OuterAppBundleInternal() {
Avi Drissman91160c632019-09-06 19:24:5827 @autoreleasepool {
28 if (!base::mac::AmIBundled()) {
29 // If unbundled (as in a test), there's no app bundle.
30 return nil;
31 }
mark@chromium.org254a99c52011-04-25 17:57:2332
Avi Drissman91160c632019-09-06 19:24:5833 if (!base::mac::IsBackgroundOnlyProcess()) {
34 // Shortcut: in the browser process, just return the main app bundle.
Avi Drissman3f5ffc12023-05-08 21:23:4635 return NSBundle.mainBundle;
Avi Drissman91160c632019-09-06 19:24:5836 }
37
38 // From C.app/Contents/Frameworks/C.framework/Versions/1.2.3.4, go up five
39 // steps to C.app.
40 base::FilePath framework_path = chrome::GetFrameworkBundlePath();
41 base::FilePath outer_app_dir =
42 framework_path.DirName().DirName().DirName().DirName().DirName();
Leonard Greyab27aae22021-05-07 14:44:0643 NSString* outer_app_dir_ns = base::SysUTF8ToNSString(outer_app_dir.value());
Avi Drissman91160c632019-09-06 19:24:5844
Avi Drissman3f5ffc12023-05-08 21:23:4645 return [NSBundle bundleWithPath:outer_app_dir_ns];
mark@chromium.org927e90a2011-04-19 02:31:4246 }
mark@chromium.org927e90a2011-04-19 02:31:4247}
48
jeremya@chromium.org7944d2482013-04-05 23:27:2149char* ProductDirNameForBundle(NSBundle* chrome_bundle) {
Avi Drissman91160c632019-09-06 19:24:5850 @autoreleasepool {
Avi Drissman3f5ffc12023-05-08 21:23:4651 const char* product_dir_name = nullptr;
mark@chromium.org1ce9fe72011-04-19 17:33:0052
Avi Drissman91160c632019-09-06 19:24:5853 NSString* product_dir_name_ns =
54 [chrome_bundle objectForInfoDictionaryKey:@"CrProductDirName"];
55 product_dir_name = [product_dir_name_ns fileSystemRepresentation];
mark@chromium.org927e90a2011-04-19 02:31:4256
Avi Drissman91160c632019-09-06 19:24:5857 if (!product_dir_name) {
Nico Weber9116a2f12019-10-07 16:32:1258#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
Avi Drissman91160c632019-09-06 19:24:5859 product_dir_name = "Google/Chrome";
mark@chromium.org927e90a2011-04-19 02:31:4260#else
Avi Drissman91160c632019-09-06 19:24:5861 product_dir_name = "Chromium";
mark@chromium.org927e90a2011-04-19 02:31:4262#endif
Avi Drissman91160c632019-09-06 19:24:5863 }
mark@chromium.org927e90a2011-04-19 02:31:4264
Avi Drissman91160c632019-09-06 19:24:5865 // Leaked, but the only caller initializes a static with this result, so it
66 // only happens once, and that's OK.
67 return strdup(product_dir_name);
68 }
mark@chromium.org927e90a2011-04-19 02:31:4269}
70
71// ProductDirName returns the name of the directory inside
72// ~/Library/Application Support that should hold the product application
73// data. This can be overridden by setting the CrProductDirName key in the
74// outer browser .app's Info.plist. The default is "Google/Chrome" for
75// officially-branded builds, and "Chromium" for unbranded builds. For the
76// official canary channel, the Info.plist will have CrProductDirName set
77// to "Google/Chrome Canary".
78std::string ProductDirName() {
jeremya@chromium.org7944d2482013-04-05 23:27:2179 // Use OuterAppBundle() to get the main app's bundle. This key needs to live
80 // in the main app's bundle because it will be set differently on the canary
81 // channel, and the autoupdate system dictates that there can be no
82 // differences between channels within the versioned directory. This would
Avi Drissmand4f07082023-05-12 18:05:4483 // normally use base::apple::FrameworkBundle(), but that references the
jeremya@chromium.org7944d2482013-04-05 23:27:2184 // framework bundle within the versioned directory. Ordinarily, the profile
85 // should not be accessed from non-browser processes, but those processes do
86 // attempt to get the profile directory, so direct them to look in the outer
87 // browser .app's Info.plist for the CrProductDirName key.
88 static const char* product_dir_name =
89 ProductDirNameForBundle(chrome::OuterAppBundle());
mark@chromium.org927e90a2011-04-19 02:31:4290 return std::string(product_dir_name);
91}
92
jeremya@chromium.org7944d2482013-04-05 23:27:2193bool GetDefaultUserDataDirectoryForProduct(const std::string& product_dir,
94 base::FilePath* result) {
95 bool success = false;
Avi Drissman7d43b4b2018-05-01 16:14:0696 if (result && base::PathService::Get(base::DIR_APP_DATA, result)) {
jeremya@chromium.org7944d2482013-04-05 23:27:2197 *result = result->Append(product_dir);
98 success = true;
99 }
100 return success;
101}
102
viettrungluu@chromium.orgadf02252010-05-18 22:09:40103} // namespace
104
pinkerton@chromium.org409993dec2009-03-03 20:23:04105namespace chrome {
106
brettw@chromium.orga7329162013-02-07 19:21:48107bool GetDefaultUserDataDirectory(base::FilePath* result) {
jeremya@chromium.org7944d2482013-04-05 23:27:21108 return GetDefaultUserDataDirectoryForProduct(ProductDirName(), result);
robertshield@chromium.orgfd1e44c2009-10-28 00:25:34109}
110
brettw@chromium.orga7329162013-02-07 19:21:48111bool GetUserDocumentsDirectory(base::FilePath* result) {
brettw@chromium.org0378bf42011-01-01 18:20:14112 return base::mac::GetUserDirectory(NSDocumentDirectory, result);
pinkerton@chromium.org409993dec2009-03-03 20:23:04113}
114
brettw@chromium.orga7329162013-02-07 19:21:48115void GetUserCacheDirectory(const base::FilePath& profile_dir,
116 base::FilePath* result) {
viettrungluu@chromium.orgb411da32010-11-24 02:23:15117 // If the profile directory is under ~/Library/Application Support,
118 // use a suitable cache directory under ~/Library/Caches. For
119 // example, a profile directory of ~/Library/Application
120 // Support/Google/Chrome/MyProfileName would use the cache directory
121 // ~/Library/Caches/Google/Chrome/MyProfileName.
122
123 // Default value in cases where any of the following fails.
124 *result = profile_dir;
125
brettw@chromium.orga7329162013-02-07 19:21:48126 base::FilePath app_data_dir;
Avi Drissman7d43b4b2018-05-01 16:14:06127 if (!base::PathService::Get(base::DIR_APP_DATA, &app_data_dir))
viettrungluu@chromium.orgb411da32010-11-24 02:23:15128 return;
brettw@chromium.orga7329162013-02-07 19:21:48129 base::FilePath cache_dir;
Avi Drissman7d43b4b2018-05-01 16:14:06130 if (!base::PathService::Get(base::DIR_CACHE, &cache_dir))
viettrungluu@chromium.orgb411da32010-11-24 02:23:15131 return;
132 if (!app_data_dir.AppendRelativePath(profile_dir, &cache_dir))
133 return;
134
135 *result = cache_dir;
136}
137
brettw@chromium.orga7329162013-02-07 19:21:48138bool GetUserDownloadsDirectory(base::FilePath* result) {
brettw@chromium.org0378bf42011-01-01 18:20:14139 return base::mac::GetUserDirectory(NSDownloadsDirectory, result);
pinkerton@chromium.org409993dec2009-03-03 20:23:04140}
141
brettw@chromium.orga7329162013-02-07 19:21:48142bool GetUserMusicDirectory(base::FilePath* result) {
thestig@chromium.orgfa9ac632012-09-14 04:18:14143 return base::mac::GetUserDirectory(NSMusicDirectory, result);
144}
145
brettw@chromium.orga7329162013-02-07 19:21:48146bool GetUserPicturesDirectory(base::FilePath* result) {
thestig@chromium.orga87c920b2012-05-17 01:06:57147 return base::mac::GetUserDirectory(NSPicturesDirectory, result);
148}
149
brettw@chromium.orga7329162013-02-07 19:21:48150bool GetUserVideosDirectory(base::FilePath* result) {
thestig@chromium.orgfa9ac632012-09-14 04:18:14151 return base::mac::GetUserDirectory(NSMoviesDirectory, result);
152}
153
brettw@chromium.orga7329162013-02-07 19:21:48154base::FilePath GetFrameworkBundlePath() {
mark@chromium.orgda90173f2009-10-07 22:57:09155 // It's tempting to use +[NSBundle bundleWithIdentifier:], but it's really
156 // slow (about 30ms on 10.5 and 10.6), despite Apple's documentation stating
157 // that it may be more efficient than +bundleForClass:. +bundleForClass:
158 // itself takes 1-2ms. Getting an NSBundle from a path, on the other hand,
159 // essentially takes no time at all, at least when the bundle has already
160 // been loaded as it will have been in this case. The FilePath operations
161 // needed to compute the framework's path are also effectively free, so that
mark@chromium.orgb88a291b2009-10-15 01:22:51162 // is the approach that is used here. NSBundle is also documented as being
163 // not thread-safe, and thread safety may be a concern here.
thomasvl@chromium.orga2126d5e2009-08-24 16:43:04164
Robert Sesek07bd6b92019-05-15 16:10:34165 // Start out with the path to the running executable.
166 base::FilePath path;
167 base::PathService::Get(base::FILE_EXE, &path);
168
169 // One step up to MacOS, another to Contents.
170 path = path.DirName().DirName();
171 DCHECK_EQ(path.BaseName().value(), "Contents");
172
173 if (base::mac::IsBackgroundOnlyProcess()) {
174 // |path| is Chromium.app/Contents/Frameworks/Chromium Framework.framework/
Robert Sesek499376682019-05-16 23:25:48175 // Versions/X/Helpers/Chromium Helper.app/Contents. Go up three times to
176 // the versioned framework directory.
177 path = path.DirName().DirName().DirName();
Robert Sesek07bd6b92019-05-15 16:10:34178 } else {
179 // |path| is Chromium.app/Contents, so go down to
Robert Sesek499376682019-05-16 23:25:48180 // Chromium.app/Contents/Frameworks/Chromium Framework.framework/Versions/X.
181 path = path.Append("Frameworks")
182 .Append(kFrameworkName)
183 .Append("Versions")
184 .Append(kChromeVersion);
Robert Sesek07bd6b92019-05-15 16:10:34185 }
Robert Sesek499376682019-05-16 23:25:48186 DCHECK_EQ(path.BaseName().value(), kChromeVersion);
187 DCHECK_EQ(path.DirName().BaseName().value(), "Versions");
188 DCHECK_EQ(path.DirName().DirName().BaseName().value(), kFrameworkName);
189 DCHECK_EQ(path.DirName().DirName().DirName().BaseName().value(),
190 "Frameworks");
191 DCHECK_EQ(path.DirName()
192 .DirName()
193 .DirName()
194 .DirName()
195 .DirName()
196 .BaseName()
197 .Extension(),
198 ".app");
Robert Sesek07bd6b92019-05-15 16:10:34199 return path;
thomasvl@chromium.orga2126d5e2009-08-24 16:43:04200}
201
brettw@chromium.orga7329162013-02-07 19:21:48202bool GetLocalLibraryDirectory(base::FilePath* result) {
brettw@chromium.org0378bf42011-01-01 18:20:14203 return base::mac::GetLocalDirectory(NSLibraryDirectory, result);
mnissler@chromium.org7c597232010-10-29 13:09:55204}
205
brettw@chromium.orga7329162013-02-07 19:21:48206bool GetGlobalApplicationSupportDirectory(base::FilePath* result) {
stuartmorgan@chromium.orgb7d1efa62012-11-16 11:22:02207 return base::mac::GetLocalDirectory(NSApplicationSupportDirectory, result);
208}
209
mark@chromium.org151c4a62011-04-22 04:15:13210NSBundle* OuterAppBundle() {
mark@chromium.org254a99c52011-04-25 17:57:23211 static NSBundle* bundle = OuterAppBundleInternal();
mark@chromium.org151c4a62011-04-22 04:15:13212 return bundle;
213}
214
pastarmovj@chromium.org288e3502012-05-09 12:35:03215bool ProcessNeedsProfileDir(const std::string& process_type) {
Avi Drissman3f5ffc12023-05-08 21:23:46216 // For now we have no reason to forbid this on other macOS as we don't
pastarmovj@chromium.org288e3502012-05-09 12:35:03217 // have the roaming profile troubles there.
218 return true;
219}
220
pinkerton@chromium.org409993dec2009-03-03 20:23:04221} // namespace chrome