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