15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shellapi.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shlobj.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/containers/hash_tables.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/files/file_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::FilePath; 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::MakeAbsoluteFilePath; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool PathProvider(int key, FilePath* result); 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool PathProviderWin(int key, FilePath* result); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool PathProviderMac(int key, FilePath* result); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool PathProviderAndroid(int key, FilePath* result); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PathProviderPosix is the default path provider on POSIX OSes other than 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mac and Android. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool PathProviderPosix(int key, FilePath* result); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef base::hash_map<int, FilePath> PathMap; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We keep a linked list of providers. In a debug build we ensure that no two 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// providers claim overlapping keys. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Provider { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathService::ProviderFunc func; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Provider* next; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int key_start; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int key_end; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_static; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Provider base_provider = { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PathProvider, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PATH_START, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PATH_END, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Provider base_provider_win = { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PathProviderWin, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &base_provider, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PATH_WIN_START, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PATH_WIN_END, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Provider base_provider_mac = { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PathProviderMac, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &base_provider, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PATH_MAC_START, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PATH_MAC_END, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Provider base_provider_android = { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PathProviderAndroid, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &base_provider, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PATH_ANDROID_START, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PATH_ANDROID_END, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Provider base_provider_posix = { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PathProviderPosix, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &base_provider, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PATH_POSIX_START, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PATH_POSIX_END, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PathData { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock lock; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathMap cache; // Cache mappings from path key to path value. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathMap overrides; // Track path overrides. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Provider* providers; // Linked list of path service providers. 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool cache_disabled; // Don't use cache if true; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PathData() : cache_disabled(false) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers = &base_provider_win; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers = &base_provider_mac; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers = &base_provider_android; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers = &base_provider_posix; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~PathData() { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Provider* p = providers; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (p) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Provider* next = p->next; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!p->is_static) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete p; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = next; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::LazyInstance<PathData> g_path_data = LAZY_INSTANCE_INITIALIZER; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PathData* GetPathData() { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_path_data.Pointer(); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tries to find |key| in the cache. |path_data| should be locked by the caller! 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LockedGetFromCache(int key, const PathData* path_data, FilePath* result) { 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (path_data->cache_disabled) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // check for a cached version 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathMap::const_iterator it = path_data->cache.find(key); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != path_data->cache.end()) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = it->second; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tries to find |key| in the overrides map. |path_data| should be locked by the 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// caller! 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LockedGetFromOverrides(int key, PathData* path_data, FilePath* result) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // check for an overridden version. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathMap::const_iterator it = path_data->overrides.find(key); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != path_data->overrides.end()) { 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!path_data->cache_disabled) 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path_data->cache[key] = it->second; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = it->second; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(brettw): this function does not handle long paths (filename > MAX_PATH) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// characters). This isn't supported very well by Windows right now, so it is 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// moot, but we should keep this in mind for the future. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PathService::Get(int key, FilePath* result) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathData* path_data = GetPathData(); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(path_data); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(result); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(key, base::DIR_CURRENT); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // special case the current directory because it can never be cached 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key == base::DIR_CURRENT) 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return base::GetCurrentDirectory(result); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Provider* provider = NULL; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock scoped_lock(path_data->lock); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LockedGetFromCache(key, path_data, result)) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LockedGetFromOverrides(key, path_data, result)) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the beginning of the list while it is still locked. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider = path_data->providers; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath path; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterating does not need the lock because only the list head might be 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // modified on another thread. 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (provider) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider->func(key, &path)) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(path.empty()) << "provider should not have modified path"; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider = provider->next; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path.empty()) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (path.ReferencesParent()) { 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure path service never returns a path with ".." in it. 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) path = MakeAbsoluteFilePath(path); 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (path.empty()) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = path; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock scoped_lock(path_data->lock); 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!path_data->cache_disabled) 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path_data->cache[key] = path; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PathService::Override(int key, const FilePath& path) { 236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Just call the full function with true for the value of |create|, and 237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // assume that |path| may not be absolute yet. 238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return OverrideAndCreateIfNeeded(key, path, false, true); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PathService::OverrideAndCreateIfNeeded(int key, 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& path, 244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool is_absolute, 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool create) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathData* path_data = GetPathData(); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(path_data); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(key, base::DIR_CURRENT) << "invalid path key"; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath file_path = path; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For some locations this will fail if called from inside the sandbox there- 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fore we protect this call with a flag. 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (create) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the directory exists. We need to do this before we translate 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // this to the absolute path because on POSIX, MakeAbsoluteFilePath fails 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // if called on a non-existent path. 2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::PathExists(file_path) && 259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) !base::CreateDirectory(file_path)) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We need to have an absolute path. 264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!is_absolute) { 265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) file_path = MakeAbsoluteFilePath(file_path); 266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (file_path.empty()) 267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return false; 268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(file_path.IsAbsolute()); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock scoped_lock(path_data->lock); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the cache now. Some of its entries could have depended 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on the value we are overriding, and are now out of sync with reality. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_data->cache.clear(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_data->overrides[key] = file_path; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PathService::RemoveOverride(int key) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathData* path_data = GetPathData(); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(path_data); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock scoped_lock(path_data->lock); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_data->overrides.find(key) == path_data->overrides.end()) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the cache now. Some of its entries could have depended on the value 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we are going to remove, and are now out of sync. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_data->cache.clear(); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_data->overrides.erase(key); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PathService::RegisterProvider(ProviderFunc func, int key_start, 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int key_end) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathData* path_data = GetPathData(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(path_data); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(key_end, key_start); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Provider* p; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = new Provider; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->is_static = false; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->func = func; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->key_start = key_start; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->key_end = key_end; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock scoped_lock(path_data->lock); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Provider *iter = path_data->providers; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (iter) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(key_start >= iter->key_end || key_end <= iter->key_start) << 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "path provider collision"; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter = iter->next; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->next = path_data->providers; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_data->providers = p; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PathService::DisableCache() { 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PathData* path_data = GetPathData(); 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(path_data); 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock scoped_lock(path_data->lock); 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path_data->cache.clear(); 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path_data->cache_disabled = true; 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 342