Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(288)

Side by Side Diff: base/path_service.cc

Issue 10909228: Add PathService::RemoveOverride to clear path overrides. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Refactored the locking semantics. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/path_service.h" 5 #include "base/path_service.h"
6 6
7 #ifdef OS_WIN 7 #ifdef OS_WIN
8 #include <windows.h> 8 #include <windows.h>
9 #include <shellapi.h> 9 #include <shellapi.h>
10 #include <shlobj.h> 10 #include <shlobj.h>
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 } 133 }
134 } 134 }
135 }; 135 };
136 136
137 static base::LazyInstance<PathData> g_path_data = LAZY_INSTANCE_INITIALIZER; 137 static base::LazyInstance<PathData> g_path_data = LAZY_INSTANCE_INITIALIZER;
138 138
139 static PathData* GetPathData() { 139 static PathData* GetPathData() {
140 return g_path_data.Pointer(); 140 return g_path_data.Pointer();
141 } 141 }
142 142
143 } // namespace 143 // Adds a value to the cache map. |path_data| should be locked by the caller!
144 void AddToCache(int key, const FilePath& path, PathData* path_data) {
145 // Save the computed path in our cache.
146 path_data->cache[key] = path;
147 }
144 148
145 149 // Tries to find |key| in the cache. |path_data| should be locked by the caller!
146 // static 150 bool GetFromCache(int key, const PathData* path_data, FilePath* result) {
147 bool PathService::GetFromCache(int key, FilePath* result) {
148 PathData* path_data = GetPathData();
149 base::AutoLock scoped_lock(path_data->lock);
150
151 // check for a cached version 151 // check for a cached version
152 PathMap::const_iterator it = path_data->cache.find(key); 152 PathMap::const_iterator it = path_data->cache.find(key);
153 if (it != path_data->cache.end()) { 153 if (it != path_data->cache.end()) {
154 *result = it->second; 154 *result = it->second;
155 return true; 155 return true;
156 } 156 }
157 return false; 157 return false;
158 } 158 }
159 159
160 // static 160 // Tries to find |key| in the overrides map. |path_data| should be locked by the
161 bool PathService::GetFromOverrides(int key, FilePath* result) { 161 // caller!
162 PathData* path_data = GetPathData(); 162 bool GetFromOverrides(int key, PathData* path_data, FilePath* result) {
jar (doing other things) 2012/09/17 17:06:08 A good readability pattern is to preface helper fu
pastarmovj 2012/09/18 14:27:13 Done.
163 base::AutoLock scoped_lock(path_data->lock);
164
165 // check for an overridden version. 163 // check for an overridden version.
166 PathMap::const_iterator it = path_data->overrides.find(key); 164 PathMap::const_iterator it = path_data->overrides.find(key);
167 if (it != path_data->overrides.end()) { 165 if (it != path_data->overrides.end()) {
166 AddToCache(key, it->second, path_data);
168 *result = it->second; 167 *result = it->second;
169 return true; 168 return true;
170 } 169 }
171 return false; 170 return false;
172 } 171 }
173 172
174 // static 173 } // namespace
175 void PathService::AddToCache(int key, const FilePath& path) {
176 PathData* path_data = GetPathData();
177 base::AutoLock scoped_lock(path_data->lock);
178 // Save the computed path in our cache.
179 path_data->cache[key] = path;
180 }
181 174
182 // TODO(brettw): this function does not handle long paths (filename > MAX_PATH) 175 // TODO(brettw): this function does not handle long paths (filename > MAX_PATH)
183 // characters). This isn't supported very well by Windows right now, so it is 176 // characters). This isn't supported very well by Windows right now, so it is
184 // moot, but we should keep this in mind for the future. 177 // moot, but we should keep this in mind for the future.
185 // static 178 // static
186 bool PathService::Get(int key, FilePath* result) { 179 bool PathService::Get(int key, FilePath* result) {
187 PathData* path_data = GetPathData(); 180 PathData* path_data = GetPathData();
188 DCHECK(path_data); 181 DCHECK(path_data);
189 DCHECK(result); 182 DCHECK(result);
190 DCHECK_GE(key, base::DIR_CURRENT); 183 DCHECK_GE(key, base::DIR_CURRENT);
191 184
192 // special case the current directory because it can never be cached 185 // special case the current directory because it can never be cached
193 if (key == base::DIR_CURRENT) 186 if (key == base::DIR_CURRENT)
194 return file_util::GetCurrentDirectory(result); 187 return file_util::GetCurrentDirectory(result);
195 188
196 if (GetFromCache(key, result)) 189 {
197 return true; 190 base::AutoLock scoped_lock(path_data->lock);
191 if (GetFromCache(key, path_data, result))
192 return true;
198 193
199 if (GetFromOverrides(key, result)) 194 if (GetFromOverrides(key, path_data, result))
200 return true; 195 return true;
196 }
201 197
202 FilePath path; 198 FilePath path;
203 199
204 // search providers for the requested path 200 // search providers for the requested path
205 // NOTE: it should be safe to iterate here without the lock 201 // NOTE: it should be safe to iterate here without the lock
206 // since RegisterProvider always prepends. 202 // since RegisterProvider always prepends.
207 Provider* provider = path_data->providers; 203 Provider* provider = path_data->providers;
208 while (provider) { 204 while (provider) {
209 if (provider->func(key, &path)) 205 if (provider->func(key, &path))
210 break; 206 break;
211 DCHECK(path.empty()) << "provider should not have modified path"; 207 DCHECK(path.empty()) << "provider should not have modified path";
212 provider = provider->next; 208 provider = provider->next;
213 } 209 }
214 210
215 if (path.empty()) 211 if (path.empty())
216 return false; 212 return false;
217 213
218 AddToCache(key, path); 214 {
215 base::AutoLock scoped_lock(path_data->lock);
216 AddToCache(key, path, path_data);
217 }
219 218
220 *result = path; 219 *result = path;
221 return true; 220 return true;
222 } 221 }
223 222
223 // static
224 bool PathService::Override(int key, const FilePath& path) { 224 bool PathService::Override(int key, const FilePath& path) {
225 // Just call the full function with true for the value of |create|. 225 // Just call the full function with true for the value of |create|.
226 return OverrideAndCreateIfNeeded(key, path, true); 226 return OverrideAndCreateIfNeeded(key, path, true);
227 } 227 }
228 228
229 // static
229 bool PathService::OverrideAndCreateIfNeeded(int key, 230 bool PathService::OverrideAndCreateIfNeeded(int key,
230 const FilePath& path, 231 const FilePath& path,
231 bool create) { 232 bool create) {
232 PathData* path_data = GetPathData(); 233 PathData* path_data = GetPathData();
233 DCHECK(path_data); 234 DCHECK(path_data);
234 DCHECK_GT(key, base::DIR_CURRENT) << "invalid path key"; 235 DCHECK_GT(key, base::DIR_CURRENT) << "invalid path key";
235 236
236 FilePath file_path = path; 237 FilePath file_path = path;
237 238
238 // For some locations this will fail if called from inside the sandbox there- 239 // For some locations this will fail if called from inside the sandbox there-
(...skipping 12 matching lines...) Expand all
251 // relative path. 252 // relative path.
252 if (!file_util::AbsolutePath(&file_path)) 253 if (!file_util::AbsolutePath(&file_path))
253 return false; 254 return false;
254 255
255 base::AutoLock scoped_lock(path_data->lock); 256 base::AutoLock scoped_lock(path_data->lock);
256 257
257 // Clear the cache now. Some of its entries could have depended 258 // Clear the cache now. Some of its entries could have depended
258 // on the value we are overriding, and are now out of sync with reality. 259 // on the value we are overriding, and are now out of sync with reality.
259 path_data->cache.clear(); 260 path_data->cache.clear();
260 261
261 path_data->cache[key] = file_path;
262 path_data->overrides[key] = file_path; 262 path_data->overrides[key] = file_path;
263 263
264 return true; 264 return true;
265 } 265 }
266 266
267 // static
268 bool PathService::RemoveOverride(int key) {
269 PathData* path_data = GetPathData();
270 DCHECK(path_data);
271
272 base::AutoLock scoped_lock(path_data->lock);
273
274 if (path_data->overrides.find(key) == path_data->overrides.end())
275 return false;
276
277 // Clear the cache now. Some of its entries could have depended on the value
278 // we are going to remove, and are now out of sync.
279 path_data->cache.clear();
280
281 path_data->overrides.erase(key);
282
283 return true;
284 }
285
286 // static
267 void PathService::RegisterProvider(ProviderFunc func, int key_start, 287 void PathService::RegisterProvider(ProviderFunc func, int key_start,
268 int key_end) { 288 int key_end) {
269 PathData* path_data = GetPathData(); 289 PathData* path_data = GetPathData();
270 DCHECK(path_data); 290 DCHECK(path_data);
271 DCHECK_GT(key_end, key_start); 291 DCHECK_GT(key_end, key_start);
272 292
273 base::AutoLock scoped_lock(path_data->lock);
274
275 Provider* p; 293 Provider* p;
276 294
277 #ifndef NDEBUG
278 p = path_data->providers;
279 while (p) {
280 DCHECK(key_start >= p->key_end || key_end <= p->key_start) <<
281 "path provider collision";
282 p = p->next;
283 }
284 #endif
285
286 p = new Provider; 295 p = new Provider;
287 p->is_static = false; 296 p->is_static = false;
288 p->func = func; 297 p->func = func;
289 p->next = path_data->providers;
290 #ifndef NDEBUG 298 #ifndef NDEBUG
291 p->key_start = key_start; 299 p->key_start = key_start;
292 p->key_end = key_end; 300 p->key_end = key_end;
293 #endif 301 #endif
302
303 base::AutoLock scoped_lock(path_data->lock);
304
305 #ifndef NDEBUG
306 Provider *iter = path_data->providers;
307 while (iter) {
308 DCHECK(key_start >= iter->key_end || key_end <= iter->key_start) <<
309 "path provider collision";
310 iter = iter->next;
311 }
312 #endif
313
314 p->next = path_data->providers;
294 path_data->providers = p; 315 path_data->providers = p;
295 } 316 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698