diff options
Diffstat (limited to 'base/path_service.cc')
-rw-r--r-- | base/path_service.cc | 341 |
1 files changed, 0 insertions, 341 deletions
diff --git a/base/path_service.cc b/base/path_service.cc deleted file mode 100644 index 3c437ee749..0000000000 --- a/base/path_service.cc +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/path_service.h" - -#if defined(OS_WIN) -#include <windows.h> -#include <shellapi.h> -#include <shlobj.h> -#endif - -#include "base/containers/hash_tables.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/synchronization/lock.h" - -using base::FilePath; -using base::MakeAbsoluteFilePath; - -namespace base { - bool PathProvider(int key, FilePath* result); -#if defined(OS_WIN) - bool PathProviderWin(int key, FilePath* result); -#elif defined(OS_MACOSX) - bool PathProviderMac(int key, FilePath* result); -#elif defined(OS_ANDROID) - bool PathProviderAndroid(int key, FilePath* result); -#elif defined(OS_POSIX) - // PathProviderPosix is the default path provider on POSIX OSes other than - // Mac and Android. - bool PathProviderPosix(int key, FilePath* result); -#endif -} // namespace base - -namespace { - -typedef base::hash_map<int, FilePath> PathMap; - -// We keep a linked list of providers. In a debug build we ensure that no two -// providers claim overlapping keys. -struct Provider { - PathService::ProviderFunc func; - struct Provider* next; -#ifndef NDEBUG - int key_start; - int key_end; -#endif - bool is_static; -}; - -Provider base_provider = { - base::PathProvider, - NULL, -#ifndef NDEBUG - base::PATH_START, - base::PATH_END, -#endif - true -}; - -#if defined(OS_WIN) -Provider base_provider_win = { - base::PathProviderWin, - &base_provider, -#ifndef NDEBUG - base::PATH_WIN_START, - base::PATH_WIN_END, -#endif - true -}; -#endif - -#if defined(OS_MACOSX) -Provider base_provider_mac = { - base::PathProviderMac, - &base_provider, -#ifndef NDEBUG - base::PATH_MAC_START, - base::PATH_MAC_END, -#endif - true -}; -#endif - -#if defined(OS_ANDROID) -Provider base_provider_android = { - base::PathProviderAndroid, - &base_provider, -#ifndef NDEBUG - base::PATH_ANDROID_START, - base::PATH_ANDROID_END, -#endif - true -}; -#endif - -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) -Provider base_provider_posix = { - base::PathProviderPosix, - &base_provider, -#ifndef NDEBUG - base::PATH_POSIX_START, - base::PATH_POSIX_END, -#endif - true -}; -#endif - - -struct PathData { - base::Lock lock; - PathMap cache; // Cache mappings from path key to path value. - PathMap overrides; // Track path overrides. - Provider* providers; // Linked list of path service providers. - bool cache_disabled; // Don't use cache if true; - - PathData() : cache_disabled(false) { -#if defined(OS_WIN) - providers = &base_provider_win; -#elif defined(OS_MACOSX) - providers = &base_provider_mac; -#elif defined(OS_ANDROID) - providers = &base_provider_android; -#elif defined(OS_POSIX) - providers = &base_provider_posix; -#endif - } - - ~PathData() { - Provider* p = providers; - while (p) { - Provider* next = p->next; - if (!p->is_static) - delete p; - p = next; - } - } -}; - -static base::LazyInstance<PathData> g_path_data = LAZY_INSTANCE_INITIALIZER; - -static PathData* GetPathData() { - return g_path_data.Pointer(); -} - -// Tries to find |key| in the cache. |path_data| should be locked by the caller! -bool LockedGetFromCache(int key, const PathData* path_data, FilePath* result) { - if (path_data->cache_disabled) - return false; - // check for a cached version - PathMap::const_iterator it = path_data->cache.find(key); - if (it != path_data->cache.end()) { - *result = it->second; - return true; - } - return false; -} - -// Tries to find |key| in the overrides map. |path_data| should be locked by the -// caller! -bool LockedGetFromOverrides(int key, PathData* path_data, FilePath* result) { - // check for an overridden version. - PathMap::const_iterator it = path_data->overrides.find(key); - if (it != path_data->overrides.end()) { - if (!path_data->cache_disabled) - path_data->cache[key] = it->second; - *result = it->second; - return true; - } - return false; -} - -} // namespace - -// TODO(brettw): this function does not handle long paths (filename > MAX_PATH) -// characters). This isn't supported very well by Windows right now, so it is -// moot, but we should keep this in mind for the future. -// static -bool PathService::Get(int key, FilePath* result) { - PathData* path_data = GetPathData(); - DCHECK(path_data); - DCHECK(result); - DCHECK_GE(key, base::DIR_CURRENT); - - // special case the current directory because it can never be cached - if (key == base::DIR_CURRENT) - return base::GetCurrentDirectory(result); - - Provider* provider = NULL; - { - base::AutoLock scoped_lock(path_data->lock); - if (LockedGetFromCache(key, path_data, result)) - return true; - - if (LockedGetFromOverrides(key, path_data, result)) - return true; - - // Get the beginning of the list while it is still locked. - provider = path_data->providers; - } - - FilePath path; - - // Iterating does not need the lock because only the list head might be - // modified on another thread. - while (provider) { - if (provider->func(key, &path)) - break; - DCHECK(path.empty()) << "provider should not have modified path"; - provider = provider->next; - } - - if (path.empty()) - return false; - - if (path.ReferencesParent()) { - // Make sure path service never returns a path with ".." in it. - path = MakeAbsoluteFilePath(path); - if (path.empty()) - return false; - } - *result = path; - - base::AutoLock scoped_lock(path_data->lock); - if (!path_data->cache_disabled) - path_data->cache[key] = path; - - return true; -} - -// static -bool PathService::Override(int key, const FilePath& path) { - // Just call the full function with true for the value of |create|, and - // assume that |path| may not be absolute yet. - return OverrideAndCreateIfNeeded(key, path, false, true); -} - -// static -bool PathService::OverrideAndCreateIfNeeded(int key, - const FilePath& path, - bool is_absolute, - bool create) { - PathData* path_data = GetPathData(); - DCHECK(path_data); - DCHECK_GT(key, base::DIR_CURRENT) << "invalid path key"; - - FilePath file_path = path; - - // For some locations this will fail if called from inside the sandbox there- - // fore we protect this call with a flag. - if (create) { - // Make sure the directory exists. We need to do this before we translate - // this to the absolute path because on POSIX, MakeAbsoluteFilePath fails - // if called on a non-existent path. - if (!base::PathExists(file_path) && - !base::CreateDirectory(file_path)) - return false; - } - - // We need to have an absolute path. - if (!is_absolute) { - file_path = MakeAbsoluteFilePath(file_path); - if (file_path.empty()) - return false; - } - DCHECK(file_path.IsAbsolute()); - - base::AutoLock scoped_lock(path_data->lock); - - // Clear the cache now. Some of its entries could have depended - // on the value we are overriding, and are now out of sync with reality. - path_data->cache.clear(); - - path_data->overrides[key] = file_path; - - return true; -} - -// static -bool PathService::RemoveOverride(int key) { - PathData* path_data = GetPathData(); - DCHECK(path_data); - - base::AutoLock scoped_lock(path_data->lock); - - if (path_data->overrides.find(key) == path_data->overrides.end()) - return false; - - // Clear the cache now. Some of its entries could have depended on the value - // we are going to remove, and are now out of sync. - path_data->cache.clear(); - - path_data->overrides.erase(key); - - return true; -} - -// static -void PathService::RegisterProvider(ProviderFunc func, int key_start, - int key_end) { - PathData* path_data = GetPathData(); - DCHECK(path_data); - DCHECK_GT(key_end, key_start); - - Provider* p; - - p = new Provider; - p->is_static = false; - p->func = func; -#ifndef NDEBUG - p->key_start = key_start; - p->key_end = key_end; -#endif - - base::AutoLock scoped_lock(path_data->lock); - -#ifndef NDEBUG - Provider *iter = path_data->providers; - while (iter) { - DCHECK(key_start >= iter->key_end || key_end <= iter->key_start) << - "path provider collision"; - iter = iter->next; - } -#endif - - p->next = path_data->providers; - path_data->providers = p; -} - -// static -void PathService::DisableCache() { - PathData* path_data = GetPathData(); - DCHECK(path_data); - - base::AutoLock scoped_lock(path_data->lock); - path_data->cache.clear(); - path_data->cache_disabled = true; -} |