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