ipc/chromium/src/base/path_service.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     5 #include "base/path_service.h"
     7 #ifdef OS_WIN
     8 #include <windows.h>
     9 #include <shellapi.h>
    10 #include <shlobj.h>
    11 #endif
    13 #include "base/file_path.h"
    14 #include "base/file_util.h"
    15 #include "base/hash_tables.h"
    16 #include "base/lock.h"
    17 #include "base/logging.h"
    18 #include "base/singleton.h"
    19 #include "base/string_util.h"
    21 namespace base {
    22   bool PathProvider(int key, FilePath* result);
    23 #if defined(OS_WIN)
    24   bool PathProviderWin(int key, FilePath* result);
    25 #elif defined(OS_MACOSX)
    26   bool PathProviderMac(int key, FilePath* result);
    27 #elif defined(OS_LINUX)
    28   bool PathProviderLinux(int key, FilePath* result);
    29 #endif
    30 }
    32 namespace {
    34 typedef base::hash_map<int, FilePath> PathMap;
    35 typedef base::hash_set<int> PathSet;
    37 // We keep a linked list of providers.  In a debug build we ensure that no two
    38 // providers claim overlapping keys.
    39 struct Provider {
    40   PathService::ProviderFunc func;
    41   struct Provider* next;
    42 #ifndef NDEBUG
    43   int key_start;
    44   int key_end;
    45 #endif
    46   bool is_static;
    47 };
    49 static Provider base_provider = {
    50   base::PathProvider,
    51   NULL,
    52 #ifndef NDEBUG
    53   base::PATH_START,
    54   base::PATH_END,
    55 #endif
    56   true
    57 };
    59 #ifdef OS_WIN
    60 static Provider base_provider_win = {
    61   base::PathProviderWin,
    62   &base_provider,
    63 #ifndef NDEBUG
    64   base::PATH_WIN_START,
    65   base::PATH_WIN_END,
    66 #endif
    67   true
    68 };
    69 #endif
    71 #ifdef OS_MACOSX
    72 static Provider base_provider_mac = {
    73   base::PathProviderMac,
    74   &base_provider,
    75 #ifndef NDEBUG
    76   base::PATH_MAC_START,
    77   base::PATH_MAC_END,
    78 #endif
    79   true
    80 };
    81 #endif
    83 #if defined(OS_LINUX)
    84 static Provider base_provider_linux = {
    85   base::PathProviderLinux,
    86   &base_provider,
    87 #ifndef NDEBUG
    88   base::PATH_LINUX_START,
    89   base::PATH_LINUX_END,
    90 #endif
    91   true
    92 };
    93 #endif
    96 struct PathData {
    97   Lock      lock;
    98   PathMap   cache;      // Track mappings from path key to path value.
    99   PathSet   overrides;  // Track whether a path has been overridden.
   100   Provider* providers;  // Linked list of path service providers.
   102   PathData() {
   103 #if defined(OS_WIN)
   104     providers = &base_provider_win;
   105 #elif defined(OS_MACOSX)
   106     providers = &base_provider_mac;
   107 #elif defined(OS_LINUX)
   108     providers = &base_provider_linux;
   109 #endif
   110   }
   112   ~PathData() {
   113     Provider* p = providers;
   114     while (p) {
   115       Provider* next = p->next;
   116       if (!p->is_static)
   117         delete p;
   118       p = next;
   119     }
   120   }
   121 };
   123 static PathData* GetPathData() {
   124   return Singleton<PathData>::get();
   125 }
   127 }  // namespace
   130 // static
   131 bool PathService::GetFromCache(int key, FilePath* result) {
   132   PathData* path_data = GetPathData();
   133   AutoLock scoped_lock(path_data->lock);
   135   // check for a cached version
   136   PathMap::const_iterator it = path_data->cache.find(key);
   137   if (it != path_data->cache.end()) {
   138     *result = it->second;
   139     return true;
   140   }
   141   return false;
   142 }
   144 // static
   145 void PathService::AddToCache(int key, const FilePath& path) {
   146   PathData* path_data = GetPathData();
   147   AutoLock scoped_lock(path_data->lock);
   148   // Save the computed path in our cache.
   149   path_data->cache[key] = path;
   150 }
   152 // TODO(brettw): this function does not handle long paths (filename > MAX_PATH)
   153 // characters). This isn't supported very well by Windows right now, so it is
   154 // moot, but we should keep this in mind for the future.
   155 // static
   156 bool PathService::Get(int key, FilePath* result) {
   157   PathData* path_data = GetPathData();
   158   DCHECK(path_data);
   159   DCHECK(result);
   160   DCHECK(key >= base::DIR_CURRENT);
   162   // special case the current directory because it can never be cached
   163   if (key == base::DIR_CURRENT)
   164     return file_util::GetCurrentDirectory(result);
   166   if (GetFromCache(key, result))
   167     return true;
   169   FilePath path;
   171   // search providers for the requested path
   172   // NOTE: it should be safe to iterate here without the lock
   173   // since RegisterProvider always prepends.
   174   Provider* provider = path_data->providers;
   175   while (provider) {
   176     if (provider->func(key, &path))
   177       break;
   178     DCHECK(path.empty()) << "provider should not have modified path";
   179     provider = provider->next;
   180   }
   182   if (path.empty())
   183     return false;
   185   AddToCache(key, path);
   187   *result = path;
   188   return true;
   189 }
   191 // static
   192 bool PathService::Get(int key, std::wstring* result) {
   193   // Deprecated compatibility function.
   194   FilePath path;
   195   if (!Get(key, &path))
   196     return false;
   197   *result = path.ToWStringHack();
   198   return true;
   199 }
   201 bool PathService::IsOverridden(int key) {
   202   PathData* path_data = GetPathData();
   203   DCHECK(path_data);
   205   AutoLock scoped_lock(path_data->lock);
   206   return path_data->overrides.find(key) != path_data->overrides.end();
   207 }
   209 bool PathService::Override(int key, const std::wstring& path) {
   210   PathData* path_data = GetPathData();
   211   DCHECK(path_data);
   212   DCHECK(key > base::DIR_CURRENT) << "invalid path key";
   214   std::wstring file_path = path;
   215 #if defined(OS_WIN)
   216   // On Windows we switch the current working directory to load plugins (at
   217   // least). That's not the case on POSIX.
   218   // Also, on POSIX, AbsolutePath fails if called on a non-existant path.
   219   if (!file_util::AbsolutePath(&file_path))
   220     return false;
   221 #endif
   223   // make sure the directory exists:
   224   if (!file_util::CreateDirectory(file_path))
   225     return false;
   227   file_util::TrimTrailingSeparator(&file_path);
   229   AutoLock scoped_lock(path_data->lock);
   230   path_data->cache[key] = FilePath::FromWStringHack(file_path);
   231   path_data->overrides.insert(key);
   232   return true;
   233 }
   235 bool PathService::SetCurrentDirectory(const std::wstring& current_directory) {
   236   return file_util::SetCurrentDirectory(current_directory);
   237 }
   239 void PathService::RegisterProvider(ProviderFunc func, int key_start,
   240                                    int key_end) {
   241   PathData* path_data = GetPathData();
   242   DCHECK(path_data);
   243   DCHECK(key_end > key_start);
   245   AutoLock scoped_lock(path_data->lock);
   247   Provider* p;
   249 #ifndef NDEBUG
   250   p = path_data->providers;
   251   while (p) {
   252     DCHECK(key_start >= p->key_end || key_end <= p->key_start) <<
   253       "path provider collision";
   254     p = p->next;
   255   }
   256 #endif
   258   p = new Provider;
   259   p->is_static = false;
   260   p->func = func;
   261   p->next = path_data->providers;
   262 #ifndef NDEBUG
   263   p->key_start = key_start;
   264   p->key_end = key_end;
   265 #endif
   266   path_data->providers = p;
   267 }

mercurial