xref: /aosp_15_r20/external/cronet/base/path_service.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/path_service.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <unordered_map>
8*6777b538SAndroid Build Coastguard Worker #include <utility>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr_exclusion.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
17*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
20*6777b538SAndroid Build Coastguard Worker #include <windows.h>
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker #include <shellapi.h>
23*6777b538SAndroid Build Coastguard Worker #include <shlobj.h>
24*6777b538SAndroid Build Coastguard Worker #endif
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker #define ENABLE_BEHAVIOUR_OVERRIDE_PROVIDER                                    \
27*6777b538SAndroid Build Coastguard Worker   ((BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID)) || \
28*6777b538SAndroid Build Coastguard Worker    BUILDFLAG(IS_WIN))
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker namespace base {
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker // Custom behaviour providers.
33*6777b538SAndroid Build Coastguard Worker bool EnvOverridePathProvider(int key, FilePath* result);
34*6777b538SAndroid Build Coastguard Worker 
35*6777b538SAndroid Build Coastguard Worker bool PathProvider(int key, FilePath* result);
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
38*6777b538SAndroid Build Coastguard Worker bool PathProviderWin(int key, FilePath* result);
39*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_MAC)
40*6777b538SAndroid Build Coastguard Worker bool PathProviderMac(int key, FilePath* result);
41*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_IOS)
42*6777b538SAndroid Build Coastguard Worker bool PathProviderIOS(int key, FilePath* result);
43*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_ANDROID)
44*6777b538SAndroid Build Coastguard Worker bool PathProviderAndroid(int key, FilePath* result);
45*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_FUCHSIA)
46*6777b538SAndroid Build Coastguard Worker bool PathProviderFuchsia(int key, FilePath* result);
47*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX)
48*6777b538SAndroid Build Coastguard Worker // PathProviderPosix is the default path provider on POSIX OSes other than
49*6777b538SAndroid Build Coastguard Worker // Mac and Android.
50*6777b538SAndroid Build Coastguard Worker bool PathProviderPosix(int key, FilePath* result);
51*6777b538SAndroid Build Coastguard Worker #endif
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker namespace {
54*6777b538SAndroid Build Coastguard Worker 
55*6777b538SAndroid Build Coastguard Worker typedef std::unordered_map<int, FilePath> PathMap;
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker // We keep a linked list of providers.  In a debug build we ensure that no two
58*6777b538SAndroid Build Coastguard Worker // providers claim overlapping keys.
59*6777b538SAndroid Build Coastguard Worker struct Provider {
60*6777b538SAndroid Build Coastguard Worker   PathService::ProviderFunc func;
61*6777b538SAndroid Build Coastguard Worker   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
62*6777b538SAndroid Build Coastguard Worker   // #reinterpret-cast-trivial-type, #global-scope
63*6777b538SAndroid Build Coastguard Worker   RAW_PTR_EXCLUSION struct Provider* next;
64*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
65*6777b538SAndroid Build Coastguard Worker   int key_start;
66*6777b538SAndroid Build Coastguard Worker   int key_end;
67*6777b538SAndroid Build Coastguard Worker #endif
68*6777b538SAndroid Build Coastguard Worker   bool is_static;
69*6777b538SAndroid Build Coastguard Worker };
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker Provider base_provider = {PathProvider, nullptr,
72*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
73*6777b538SAndroid Build Coastguard Worker                           PATH_START, PATH_END,
74*6777b538SAndroid Build Coastguard Worker #endif
75*6777b538SAndroid Build Coastguard Worker                           true};
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
78*6777b538SAndroid Build Coastguard Worker Provider win_provider = {PathProviderWin, &base_provider,
79*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
80*6777b538SAndroid Build Coastguard Worker                          PATH_WIN_START, PATH_WIN_END,
81*6777b538SAndroid Build Coastguard Worker #endif
82*6777b538SAndroid Build Coastguard Worker                          true};
83*6777b538SAndroid Build Coastguard Worker Provider base_provider_win = {EnvOverridePathProvider, &win_provider,
84*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
85*6777b538SAndroid Build Coastguard Worker                               PATH_START, PATH_END,
86*6777b538SAndroid Build Coastguard Worker #endif
87*6777b538SAndroid Build Coastguard Worker                               true};
88*6777b538SAndroid Build Coastguard Worker #endif
89*6777b538SAndroid Build Coastguard Worker 
90*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_MAC)
91*6777b538SAndroid Build Coastguard Worker Provider base_provider_mac = {
92*6777b538SAndroid Build Coastguard Worker   PathProviderMac,
93*6777b538SAndroid Build Coastguard Worker   &base_provider,
94*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
95*6777b538SAndroid Build Coastguard Worker   PATH_MAC_START,
96*6777b538SAndroid Build Coastguard Worker   PATH_MAC_END,
97*6777b538SAndroid Build Coastguard Worker #endif
98*6777b538SAndroid Build Coastguard Worker   true
99*6777b538SAndroid Build Coastguard Worker };
100*6777b538SAndroid Build Coastguard Worker #endif
101*6777b538SAndroid Build Coastguard Worker 
102*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS)
103*6777b538SAndroid Build Coastguard Worker Provider base_provider_ios = {
104*6777b538SAndroid Build Coastguard Worker   PathProviderIOS,
105*6777b538SAndroid Build Coastguard Worker   &base_provider,
106*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
107*6777b538SAndroid Build Coastguard Worker   PATH_IOS_START,
108*6777b538SAndroid Build Coastguard Worker   PATH_IOS_END,
109*6777b538SAndroid Build Coastguard Worker #endif
110*6777b538SAndroid Build Coastguard Worker   true
111*6777b538SAndroid Build Coastguard Worker };
112*6777b538SAndroid Build Coastguard Worker #endif
113*6777b538SAndroid Build Coastguard Worker 
114*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
115*6777b538SAndroid Build Coastguard Worker Provider base_provider_android = {
116*6777b538SAndroid Build Coastguard Worker   PathProviderAndroid,
117*6777b538SAndroid Build Coastguard Worker   &base_provider,
118*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
119*6777b538SAndroid Build Coastguard Worker   PATH_ANDROID_START,
120*6777b538SAndroid Build Coastguard Worker   PATH_ANDROID_END,
121*6777b538SAndroid Build Coastguard Worker #endif
122*6777b538SAndroid Build Coastguard Worker   true
123*6777b538SAndroid Build Coastguard Worker };
124*6777b538SAndroid Build Coastguard Worker #endif
125*6777b538SAndroid Build Coastguard Worker 
126*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_FUCHSIA)
127*6777b538SAndroid Build Coastguard Worker Provider base_provider_fuchsia = {PathProviderFuchsia, &base_provider,
128*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
129*6777b538SAndroid Build Coastguard Worker                                   0, 0,
130*6777b538SAndroid Build Coastguard Worker #endif
131*6777b538SAndroid Build Coastguard Worker                                   true};
132*6777b538SAndroid Build Coastguard Worker #endif
133*6777b538SAndroid Build Coastguard Worker 
134*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID)
135*6777b538SAndroid Build Coastguard Worker Provider posix_provider = {PathProviderPosix, &base_provider,
136*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
137*6777b538SAndroid Build Coastguard Worker                            PATH_POSIX_START, PATH_POSIX_END,
138*6777b538SAndroid Build Coastguard Worker #endif
139*6777b538SAndroid Build Coastguard Worker                            true};
140*6777b538SAndroid Build Coastguard Worker Provider base_provider_posix = {EnvOverridePathProvider, &posix_provider,
141*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
142*6777b538SAndroid Build Coastguard Worker                                 PATH_START, PATH_END,
143*6777b538SAndroid Build Coastguard Worker #endif
144*6777b538SAndroid Build Coastguard Worker                                 true};
145*6777b538SAndroid Build Coastguard Worker #endif
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker 
148*6777b538SAndroid Build Coastguard Worker struct PathData {
149*6777b538SAndroid Build Coastguard Worker   Lock lock;
150*6777b538SAndroid Build Coastguard Worker   PathMap cache;        // Cache mappings from path key to path value.
151*6777b538SAndroid Build Coastguard Worker   PathMap overrides;    // Track path overrides.
152*6777b538SAndroid Build Coastguard Worker   raw_ptr<Provider> providers;  // Linked list of path service providers.
153*6777b538SAndroid Build Coastguard Worker   bool cache_disabled;  // Don't use cache if true;
154*6777b538SAndroid Build Coastguard Worker 
PathDatabase::__anon7900a43c0111::PathData155*6777b538SAndroid Build Coastguard Worker   PathData() : cache_disabled(false) {
156*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
157*6777b538SAndroid Build Coastguard Worker     providers = &base_provider_win;
158*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_MAC)
159*6777b538SAndroid Build Coastguard Worker     providers = &base_provider_mac;
160*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_IOS)
161*6777b538SAndroid Build Coastguard Worker     providers = &base_provider_ios;
162*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_ANDROID)
163*6777b538SAndroid Build Coastguard Worker     providers = &base_provider_android;
164*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_FUCHSIA)
165*6777b538SAndroid Build Coastguard Worker     providers = &base_provider_fuchsia;
166*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX)
167*6777b538SAndroid Build Coastguard Worker     providers = &base_provider_posix;
168*6777b538SAndroid Build Coastguard Worker #endif
169*6777b538SAndroid Build Coastguard Worker   }
170*6777b538SAndroid Build Coastguard Worker };
171*6777b538SAndroid Build Coastguard Worker 
GetPathData()172*6777b538SAndroid Build Coastguard Worker static PathData* GetPathData() {
173*6777b538SAndroid Build Coastguard Worker   static auto* path_data = new PathData();
174*6777b538SAndroid Build Coastguard Worker   return path_data;
175*6777b538SAndroid Build Coastguard Worker }
176*6777b538SAndroid Build Coastguard Worker 
177*6777b538SAndroid Build Coastguard Worker // Tries to find |key| in the cache.
LockedGetFromCache(int key,const PathData * path_data,FilePath * result)178*6777b538SAndroid Build Coastguard Worker bool LockedGetFromCache(int key, const PathData* path_data, FilePath* result)
179*6777b538SAndroid Build Coastguard Worker     EXCLUSIVE_LOCKS_REQUIRED(path_data->lock) {
180*6777b538SAndroid Build Coastguard Worker   if (path_data->cache_disabled)
181*6777b538SAndroid Build Coastguard Worker     return false;
182*6777b538SAndroid Build Coastguard Worker   // check for a cached version
183*6777b538SAndroid Build Coastguard Worker   auto it = path_data->cache.find(key);
184*6777b538SAndroid Build Coastguard Worker   if (it != path_data->cache.end()) {
185*6777b538SAndroid Build Coastguard Worker     *result = it->second;
186*6777b538SAndroid Build Coastguard Worker     return true;
187*6777b538SAndroid Build Coastguard Worker   }
188*6777b538SAndroid Build Coastguard Worker   return false;
189*6777b538SAndroid Build Coastguard Worker }
190*6777b538SAndroid Build Coastguard Worker 
191*6777b538SAndroid Build Coastguard Worker // Tries to find |key| in the overrides map.
LockedGetFromOverrides(int key,PathData * path_data,FilePath * result)192*6777b538SAndroid Build Coastguard Worker bool LockedGetFromOverrides(int key, PathData* path_data, FilePath* result)
193*6777b538SAndroid Build Coastguard Worker     EXCLUSIVE_LOCKS_REQUIRED(path_data->lock) {
194*6777b538SAndroid Build Coastguard Worker   // check for an overridden version.
195*6777b538SAndroid Build Coastguard Worker   PathMap::const_iterator it = path_data->overrides.find(key);
196*6777b538SAndroid Build Coastguard Worker   if (it != path_data->overrides.end()) {
197*6777b538SAndroid Build Coastguard Worker     if (!path_data->cache_disabled)
198*6777b538SAndroid Build Coastguard Worker       path_data->cache[key] = it->second;
199*6777b538SAndroid Build Coastguard Worker     *result = it->second;
200*6777b538SAndroid Build Coastguard Worker     return true;
201*6777b538SAndroid Build Coastguard Worker   }
202*6777b538SAndroid Build Coastguard Worker   return false;
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker 
205*6777b538SAndroid Build Coastguard Worker }  // namespace
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker // TODO(brettw): this function does not handle long paths (filename > MAX_PATH)
208*6777b538SAndroid Build Coastguard Worker // characters). This isn't supported very well by Windows right now, so it is
209*6777b538SAndroid Build Coastguard Worker // moot, but we should keep this in mind for the future.
210*6777b538SAndroid Build Coastguard Worker // static
Get(int key,FilePath * result)211*6777b538SAndroid Build Coastguard Worker bool PathService::Get(int key, FilePath* result) {
212*6777b538SAndroid Build Coastguard Worker   PathData* path_data = GetPathData();
213*6777b538SAndroid Build Coastguard Worker   DCHECK(path_data);
214*6777b538SAndroid Build Coastguard Worker   DCHECK(result);
215*6777b538SAndroid Build Coastguard Worker   DCHECK_GT(key, PATH_START);
216*6777b538SAndroid Build Coastguard Worker 
217*6777b538SAndroid Build Coastguard Worker   // Special case the current directory because it can never be cached.
218*6777b538SAndroid Build Coastguard Worker   if (key == DIR_CURRENT)
219*6777b538SAndroid Build Coastguard Worker     return GetCurrentDirectory(result);
220*6777b538SAndroid Build Coastguard Worker 
221*6777b538SAndroid Build Coastguard Worker   Provider* provider = nullptr;
222*6777b538SAndroid Build Coastguard Worker   {
223*6777b538SAndroid Build Coastguard Worker     AutoLock scoped_lock(path_data->lock);
224*6777b538SAndroid Build Coastguard Worker     if (LockedGetFromCache(key, path_data, result))
225*6777b538SAndroid Build Coastguard Worker       return true;
226*6777b538SAndroid Build Coastguard Worker 
227*6777b538SAndroid Build Coastguard Worker     if (LockedGetFromOverrides(key, path_data, result))
228*6777b538SAndroid Build Coastguard Worker       return true;
229*6777b538SAndroid Build Coastguard Worker 
230*6777b538SAndroid Build Coastguard Worker     // Get the beginning of the list while it is still locked.
231*6777b538SAndroid Build Coastguard Worker     provider = path_data->providers;
232*6777b538SAndroid Build Coastguard Worker   }
233*6777b538SAndroid Build Coastguard Worker 
234*6777b538SAndroid Build Coastguard Worker   FilePath path;
235*6777b538SAndroid Build Coastguard Worker 
236*6777b538SAndroid Build Coastguard Worker   // Iterating does not need the lock because only the list head might be
237*6777b538SAndroid Build Coastguard Worker   // modified on another thread.
238*6777b538SAndroid Build Coastguard Worker   while (provider) {
239*6777b538SAndroid Build Coastguard Worker     if (provider->func(key, &path))
240*6777b538SAndroid Build Coastguard Worker       break;
241*6777b538SAndroid Build Coastguard Worker     DCHECK(path.empty()) << "provider should not have modified path";
242*6777b538SAndroid Build Coastguard Worker     provider = provider->next;
243*6777b538SAndroid Build Coastguard Worker   }
244*6777b538SAndroid Build Coastguard Worker 
245*6777b538SAndroid Build Coastguard Worker   if (path.empty())
246*6777b538SAndroid Build Coastguard Worker     return false;
247*6777b538SAndroid Build Coastguard Worker 
248*6777b538SAndroid Build Coastguard Worker   if (path.ReferencesParent()) {
249*6777b538SAndroid Build Coastguard Worker     // Make sure path service never returns a path with ".." in it.
250*6777b538SAndroid Build Coastguard Worker     path = MakeAbsoluteFilePath(path);
251*6777b538SAndroid Build Coastguard Worker     if (path.empty())
252*6777b538SAndroid Build Coastguard Worker       return false;
253*6777b538SAndroid Build Coastguard Worker   }
254*6777b538SAndroid Build Coastguard Worker   *result = path;
255*6777b538SAndroid Build Coastguard Worker 
256*6777b538SAndroid Build Coastguard Worker   AutoLock scoped_lock(path_data->lock);
257*6777b538SAndroid Build Coastguard Worker   if (!path_data->cache_disabled)
258*6777b538SAndroid Build Coastguard Worker     path_data->cache[key] = path;
259*6777b538SAndroid Build Coastguard Worker 
260*6777b538SAndroid Build Coastguard Worker   return true;
261*6777b538SAndroid Build Coastguard Worker }
262*6777b538SAndroid Build Coastguard Worker 
CheckedGet(int key)263*6777b538SAndroid Build Coastguard Worker FilePath PathService::CheckedGet(int key) {
264*6777b538SAndroid Build Coastguard Worker   FilePath path;
265*6777b538SAndroid Build Coastguard Worker   LOG_IF(FATAL, !Get(key, &path)) << "Failed to get the path for " << key;
266*6777b538SAndroid Build Coastguard Worker   return path;
267*6777b538SAndroid Build Coastguard Worker }
268*6777b538SAndroid Build Coastguard Worker 
269*6777b538SAndroid Build Coastguard Worker // static
Override(int key,const FilePath & path)270*6777b538SAndroid Build Coastguard Worker bool PathService::Override(int key, const FilePath& path) {
271*6777b538SAndroid Build Coastguard Worker   // Just call the full function with true for the value of |create|, and
272*6777b538SAndroid Build Coastguard Worker   // assume that |path| may not be absolute yet.
273*6777b538SAndroid Build Coastguard Worker   return OverrideAndCreateIfNeeded(key, path, false, true);
274*6777b538SAndroid Build Coastguard Worker }
275*6777b538SAndroid Build Coastguard Worker 
276*6777b538SAndroid Build Coastguard Worker // static
OverrideAndCreateIfNeeded(int key,const FilePath & path,bool is_absolute,bool create)277*6777b538SAndroid Build Coastguard Worker bool PathService::OverrideAndCreateIfNeeded(int key,
278*6777b538SAndroid Build Coastguard Worker                                             const FilePath& path,
279*6777b538SAndroid Build Coastguard Worker                                             bool is_absolute,
280*6777b538SAndroid Build Coastguard Worker                                             bool create) {
281*6777b538SAndroid Build Coastguard Worker   PathData* path_data = GetPathData();
282*6777b538SAndroid Build Coastguard Worker   DCHECK(path_data);
283*6777b538SAndroid Build Coastguard Worker   DCHECK_GT(key, PATH_START) << "invalid path key";
284*6777b538SAndroid Build Coastguard Worker 
285*6777b538SAndroid Build Coastguard Worker   FilePath file_path = path;
286*6777b538SAndroid Build Coastguard Worker 
287*6777b538SAndroid Build Coastguard Worker   // Create the directory if requested by the caller. Do this before resolving
288*6777b538SAndroid Build Coastguard Worker   // `file_path` to an absolute path because on POSIX, MakeAbsoluteFilePath
289*6777b538SAndroid Build Coastguard Worker   // requires that the path exists.
290*6777b538SAndroid Build Coastguard Worker   if (create && !CreateDirectory(file_path)) {
291*6777b538SAndroid Build Coastguard Worker     return false;
292*6777b538SAndroid Build Coastguard Worker   }
293*6777b538SAndroid Build Coastguard Worker 
294*6777b538SAndroid Build Coastguard Worker   // We need to have an absolute path.
295*6777b538SAndroid Build Coastguard Worker   if (!is_absolute) {
296*6777b538SAndroid Build Coastguard Worker     file_path = MakeAbsoluteFilePath(file_path);
297*6777b538SAndroid Build Coastguard Worker     if (file_path.empty())
298*6777b538SAndroid Build Coastguard Worker       return false;
299*6777b538SAndroid Build Coastguard Worker   }
300*6777b538SAndroid Build Coastguard Worker   DCHECK(file_path.IsAbsolute());
301*6777b538SAndroid Build Coastguard Worker 
302*6777b538SAndroid Build Coastguard Worker   AutoLock scoped_lock(path_data->lock);
303*6777b538SAndroid Build Coastguard Worker 
304*6777b538SAndroid Build Coastguard Worker   // Clear the cache now. Some of its entries could have depended
305*6777b538SAndroid Build Coastguard Worker   // on the value we are overriding, and are now out of sync with reality.
306*6777b538SAndroid Build Coastguard Worker   path_data->cache.clear();
307*6777b538SAndroid Build Coastguard Worker 
308*6777b538SAndroid Build Coastguard Worker   path_data->overrides[key] = std::move(file_path);
309*6777b538SAndroid Build Coastguard Worker 
310*6777b538SAndroid Build Coastguard Worker   return true;
311*6777b538SAndroid Build Coastguard Worker }
312*6777b538SAndroid Build Coastguard Worker 
313*6777b538SAndroid Build Coastguard Worker // static
RemoveOverrideForTests(int key)314*6777b538SAndroid Build Coastguard Worker bool PathService::RemoveOverrideForTests(int key) {
315*6777b538SAndroid Build Coastguard Worker   PathData* path_data = GetPathData();
316*6777b538SAndroid Build Coastguard Worker   DCHECK(path_data);
317*6777b538SAndroid Build Coastguard Worker 
318*6777b538SAndroid Build Coastguard Worker   AutoLock scoped_lock(path_data->lock);
319*6777b538SAndroid Build Coastguard Worker 
320*6777b538SAndroid Build Coastguard Worker   if (path_data->overrides.find(key) == path_data->overrides.end())
321*6777b538SAndroid Build Coastguard Worker     return false;
322*6777b538SAndroid Build Coastguard Worker 
323*6777b538SAndroid Build Coastguard Worker   // Clear the cache now. Some of its entries could have depended on the value
324*6777b538SAndroid Build Coastguard Worker   // we are going to remove, and are now out of sync.
325*6777b538SAndroid Build Coastguard Worker   path_data->cache.clear();
326*6777b538SAndroid Build Coastguard Worker 
327*6777b538SAndroid Build Coastguard Worker   path_data->overrides.erase(key);
328*6777b538SAndroid Build Coastguard Worker 
329*6777b538SAndroid Build Coastguard Worker   return true;
330*6777b538SAndroid Build Coastguard Worker }
331*6777b538SAndroid Build Coastguard Worker 
332*6777b538SAndroid Build Coastguard Worker // static
IsOverriddenForTesting(int key)333*6777b538SAndroid Build Coastguard Worker bool PathService::IsOverriddenForTesting(int key) {
334*6777b538SAndroid Build Coastguard Worker   PathData* path_data = GetPathData();
335*6777b538SAndroid Build Coastguard Worker   DCHECK(path_data);
336*6777b538SAndroid Build Coastguard Worker 
337*6777b538SAndroid Build Coastguard Worker   AutoLock scoped_lock(path_data->lock);
338*6777b538SAndroid Build Coastguard Worker 
339*6777b538SAndroid Build Coastguard Worker   return path_data->overrides.find(key) != path_data->overrides.end();
340*6777b538SAndroid Build Coastguard Worker }
341*6777b538SAndroid Build Coastguard Worker 
342*6777b538SAndroid Build Coastguard Worker // static
RegisterProvider(ProviderFunc func,int key_start,int key_end)343*6777b538SAndroid Build Coastguard Worker void PathService::RegisterProvider(ProviderFunc func, int key_start,
344*6777b538SAndroid Build Coastguard Worker                                    int key_end) {
345*6777b538SAndroid Build Coastguard Worker   PathData* path_data = GetPathData();
346*6777b538SAndroid Build Coastguard Worker   DCHECK(path_data);
347*6777b538SAndroid Build Coastguard Worker   DCHECK_GT(key_end, key_start);
348*6777b538SAndroid Build Coastguard Worker 
349*6777b538SAndroid Build Coastguard Worker   Provider* p;
350*6777b538SAndroid Build Coastguard Worker 
351*6777b538SAndroid Build Coastguard Worker   p = new Provider;
352*6777b538SAndroid Build Coastguard Worker   p->is_static = false;
353*6777b538SAndroid Build Coastguard Worker   p->func = func;
354*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
355*6777b538SAndroid Build Coastguard Worker   p->key_start = key_start;
356*6777b538SAndroid Build Coastguard Worker   p->key_end = key_end;
357*6777b538SAndroid Build Coastguard Worker #endif
358*6777b538SAndroid Build Coastguard Worker 
359*6777b538SAndroid Build Coastguard Worker   AutoLock scoped_lock(path_data->lock);
360*6777b538SAndroid Build Coastguard Worker 
361*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
362*6777b538SAndroid Build Coastguard Worker   Provider *iter = path_data->providers;
363*6777b538SAndroid Build Coastguard Worker   while (iter) {
364*6777b538SAndroid Build Coastguard Worker     DCHECK(key_start >= iter->key_end || key_end <= iter->key_start) <<
365*6777b538SAndroid Build Coastguard Worker       "path provider collision";
366*6777b538SAndroid Build Coastguard Worker     iter = iter->next;
367*6777b538SAndroid Build Coastguard Worker   }
368*6777b538SAndroid Build Coastguard Worker #endif
369*6777b538SAndroid Build Coastguard Worker 
370*6777b538SAndroid Build Coastguard Worker   p->next = path_data->providers;
371*6777b538SAndroid Build Coastguard Worker   path_data->providers = p;
372*6777b538SAndroid Build Coastguard Worker }
373*6777b538SAndroid Build Coastguard Worker 
374*6777b538SAndroid Build Coastguard Worker // static
DisableCache()375*6777b538SAndroid Build Coastguard Worker void PathService::DisableCache() {
376*6777b538SAndroid Build Coastguard Worker   PathData* path_data = GetPathData();
377*6777b538SAndroid Build Coastguard Worker   DCHECK(path_data);
378*6777b538SAndroid Build Coastguard Worker 
379*6777b538SAndroid Build Coastguard Worker   AutoLock scoped_lock(path_data->lock);
380*6777b538SAndroid Build Coastguard Worker   path_data->cache.clear();
381*6777b538SAndroid Build Coastguard Worker   path_data->cache_disabled = true;
382*6777b538SAndroid Build Coastguard Worker }
383*6777b538SAndroid Build Coastguard Worker 
384*6777b538SAndroid Build Coastguard Worker }  // namespace base
385