OLD | NEW |
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 "chrome/browser/download/download_path_reservation_tracker.h" | 5 #include "chrome/browser/download/download_path_reservation_tracker.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 DownloadItem* download_item_; | 63 DownloadItem* download_item_; |
64 | 64 |
65 // Last known target path for the download. | 65 // Last known target path for the download. |
66 base::FilePath last_target_path_; | 66 base::FilePath last_target_path_; |
67 | 67 |
68 DISALLOW_COPY_AND_ASSIGN(DownloadItemObserver); | 68 DISALLOW_COPY_AND_ASSIGN(DownloadItemObserver); |
69 }; | 69 }; |
70 | 70 |
71 // Returns true if the given path is in use by a path reservation. | 71 // Returns true if the given path is in use by a path reservation. |
72 bool IsPathReserved(const base::FilePath& path) { | 72 bool IsPathReserved(const base::FilePath& path) { |
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 73 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
74 // No reservation map => no reservations. | 74 // No reservation map => no reservations. |
75 if (g_reservation_map == NULL) | 75 if (g_reservation_map == NULL) |
76 return false; | 76 return false; |
77 // Unfortunately path normalization doesn't work reliably for non-existant | 77 // Unfortunately path normalization doesn't work reliably for non-existant |
78 // files. So given a FilePath, we can't derive a normalized key that we can | 78 // files. So given a FilePath, we can't derive a normalized key that we can |
79 // use for lookups. We only expect a small number of concurrent downloads at | 79 // use for lookups. We only expect a small number of concurrent downloads at |
80 // any given time, so going through all of them shouldn't be too slow. | 80 // any given time, so going through all of them shouldn't be too slow. |
81 for (ReservationMap::const_iterator iter = g_reservation_map->begin(); | 81 for (ReservationMap::const_iterator iter = g_reservation_map->begin(); |
82 iter != g_reservation_map->end(); ++iter) { | 82 iter != g_reservation_map->end(); ++iter) { |
83 if (iter->second == path) | 83 if (iter->second == path) |
84 return true; | 84 return true; |
85 } | 85 } |
86 return false; | 86 return false; |
87 } | 87 } |
88 | 88 |
89 // Returns true if the given path is in use by any path reservation or the | 89 // Returns true if the given path is in use by any path reservation or the |
90 // file system. Called on the FILE thread. | 90 // file system. Called on the FILE thread. |
91 bool IsPathInUse(const base::FilePath& path) { | 91 bool IsPathInUse(const base::FilePath& path) { |
92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 92 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
93 // If there is a reservation, then the path is in use. | 93 // If there is a reservation, then the path is in use. |
94 if (IsPathReserved(path)) | 94 if (IsPathReserved(path)) |
95 return true; | 95 return true; |
96 | 96 |
97 // If the path exists in the file system, then the path is in use. | 97 // If the path exists in the file system, then the path is in use. |
98 if (base::PathExists(path)) | 98 if (base::PathExists(path)) |
99 return true; | 99 return true; |
100 | 100 |
101 return false; | 101 return false; |
102 } | 102 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 // - Truncates the suggested name if it exceeds the filesystem's limit. | 148 // - Truncates the suggested name if it exceeds the filesystem's limit. |
149 // - Uniquifies |suggested_path| if |should_uniquify_path| is true. | 149 // - Uniquifies |suggested_path| if |should_uniquify_path| is true. |
150 // - Returns true if |reserved_path| has been successfully verified. | 150 // - Returns true if |reserved_path| has been successfully verified. |
151 bool CreateReservation( | 151 bool CreateReservation( |
152 ReservationKey key, | 152 ReservationKey key, |
153 const base::FilePath& suggested_path, | 153 const base::FilePath& suggested_path, |
154 const base::FilePath& default_download_path, | 154 const base::FilePath& default_download_path, |
155 bool create_directory, | 155 bool create_directory, |
156 DownloadPathReservationTracker::FilenameConflictAction conflict_action, | 156 DownloadPathReservationTracker::FilenameConflictAction conflict_action, |
157 base::FilePath* reserved_path) { | 157 base::FilePath* reserved_path) { |
158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 158 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
159 DCHECK(suggested_path.IsAbsolute()); | 159 DCHECK(suggested_path.IsAbsolute()); |
160 | 160 |
161 // Create a reservation map if one doesn't exist. It will be automatically | 161 // Create a reservation map if one doesn't exist. It will be automatically |
162 // deleted when all the reservations are revoked. | 162 // deleted when all the reservations are revoked. |
163 if (g_reservation_map == NULL) | 163 if (g_reservation_map == NULL) |
164 g_reservation_map = new ReservationMap; | 164 g_reservation_map = new ReservationMap; |
165 | 165 |
166 ReservationMap& reservations = *g_reservation_map; | 166 ReservationMap& reservations = *g_reservation_map; |
167 DCHECK(!ContainsKey(reservations, key)); | 167 DCHECK(!ContainsKey(reservations, key)); |
168 | 168 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 | 242 |
243 reservations[key] = target_path; | 243 reservations[key] = target_path; |
244 bool verified = (is_path_writeable && !has_conflicts && !name_too_long); | 244 bool verified = (is_path_writeable && !has_conflicts && !name_too_long); |
245 *reserved_path = target_path; | 245 *reserved_path = target_path; |
246 return verified; | 246 return verified; |
247 } | 247 } |
248 | 248 |
249 // Called on the FILE thread to update the path of the reservation associated | 249 // Called on the FILE thread to update the path of the reservation associated |
250 // with |key| to |new_path|. | 250 // with |key| to |new_path|. |
251 void UpdateReservation(ReservationKey key, const base::FilePath& new_path) { | 251 void UpdateReservation(ReservationKey key, const base::FilePath& new_path) { |
252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 252 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
253 DCHECK(g_reservation_map != NULL); | 253 DCHECK(g_reservation_map != NULL); |
254 ReservationMap::iterator iter = g_reservation_map->find(key); | 254 ReservationMap::iterator iter = g_reservation_map->find(key); |
255 if (iter != g_reservation_map->end()) { | 255 if (iter != g_reservation_map->end()) { |
256 iter->second = new_path; | 256 iter->second = new_path; |
257 } else { | 257 } else { |
258 // This would happen if an UpdateReservation() notification was scheduled on | 258 // This would happen if an UpdateReservation() notification was scheduled on |
259 // the FILE thread before ReserveInternal(), or after a Revoke() | 259 // the FILE thread before ReserveInternal(), or after a Revoke() |
260 // call. Neither should happen. | 260 // call. Neither should happen. |
261 NOTREACHED(); | 261 NOTREACHED(); |
262 } | 262 } |
263 } | 263 } |
264 | 264 |
265 // Called on the FILE thread to remove the path reservation associated with | 265 // Called on the FILE thread to remove the path reservation associated with |
266 // |key|. | 266 // |key|. |
267 void RevokeReservation(ReservationKey key) { | 267 void RevokeReservation(ReservationKey key) { |
268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 268 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
269 DCHECK(g_reservation_map != NULL); | 269 DCHECK(g_reservation_map != NULL); |
270 DCHECK(ContainsKey(*g_reservation_map, key)); | 270 DCHECK(ContainsKey(*g_reservation_map, key)); |
271 g_reservation_map->erase(key); | 271 g_reservation_map->erase(key); |
272 if (g_reservation_map->size() == 0) { | 272 if (g_reservation_map->size() == 0) { |
273 // No more reservations. Delete map. | 273 // No more reservations. Delete map. |
274 delete g_reservation_map; | 274 delete g_reservation_map; |
275 g_reservation_map = NULL; | 275 g_reservation_map = NULL; |
276 } | 276 } |
277 } | 277 } |
278 | 278 |
279 void RunGetReservedPathCallback( | 279 void RunGetReservedPathCallback( |
280 const DownloadPathReservationTracker::ReservedPathCallback& callback, | 280 const DownloadPathReservationTracker::ReservedPathCallback& callback, |
281 const base::FilePath* reserved_path, | 281 const base::FilePath* reserved_path, |
282 bool verified) { | 282 bool verified) { |
283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 283 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
284 callback.Run(*reserved_path, verified); | 284 callback.Run(*reserved_path, verified); |
285 } | 285 } |
286 | 286 |
287 DownloadItemObserver::DownloadItemObserver(DownloadItem* download_item) | 287 DownloadItemObserver::DownloadItemObserver(DownloadItem* download_item) |
288 : download_item_(download_item), | 288 : download_item_(download_item), |
289 last_target_path_(download_item->GetTargetFilePath()) { | 289 last_target_path_(download_item->GetTargetFilePath()) { |
290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 290 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
291 download_item_->AddObserver(this); | 291 download_item_->AddObserver(this); |
292 } | 292 } |
293 | 293 |
294 DownloadItemObserver::~DownloadItemObserver() { | 294 DownloadItemObserver::~DownloadItemObserver() { |
295 download_item_->RemoveObserver(this); | 295 download_item_->RemoveObserver(this); |
296 } | 296 } |
297 | 297 |
298 void DownloadItemObserver::OnDownloadUpdated(DownloadItem* download) { | 298 void DownloadItemObserver::OnDownloadUpdated(DownloadItem* download) { |
299 switch (download->GetState()) { | 299 switch (download->GetState()) { |
300 case DownloadItem::IN_PROGRESS: { | 300 case DownloadItem::IN_PROGRESS: { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 } // namespace | 343 } // namespace |
344 | 344 |
345 // static | 345 // static |
346 void DownloadPathReservationTracker::GetReservedPath( | 346 void DownloadPathReservationTracker::GetReservedPath( |
347 DownloadItem* download_item, | 347 DownloadItem* download_item, |
348 const base::FilePath& target_path, | 348 const base::FilePath& target_path, |
349 const base::FilePath& default_path, | 349 const base::FilePath& default_path, |
350 bool create_directory, | 350 bool create_directory, |
351 FilenameConflictAction conflict_action, | 351 FilenameConflictAction conflict_action, |
352 const ReservedPathCallback& callback) { | 352 const ReservedPathCallback& callback) { |
353 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 353 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
354 // Attach an observer to the download item so that we know when the target | 354 // Attach an observer to the download item so that we know when the target |
355 // path changes and/or the download is no longer active. | 355 // path changes and/or the download is no longer active. |
356 new DownloadItemObserver(download_item); | 356 new DownloadItemObserver(download_item); |
357 // DownloadItemObserver deletes itself. | 357 // DownloadItemObserver deletes itself. |
358 | 358 |
359 base::FilePath* reserved_path = new base::FilePath; | 359 base::FilePath* reserved_path = new base::FilePath; |
360 BrowserThread::PostTaskAndReplyWithResult( | 360 BrowserThread::PostTaskAndReplyWithResult( |
361 BrowserThread::FILE, | 361 BrowserThread::FILE, |
362 FROM_HERE, | 362 FROM_HERE, |
363 base::Bind(&CreateReservation, | 363 base::Bind(&CreateReservation, |
364 download_item, | 364 download_item, |
365 target_path, | 365 target_path, |
366 default_path, | 366 default_path, |
367 create_directory, | 367 create_directory, |
368 conflict_action, | 368 conflict_action, |
369 reserved_path), | 369 reserved_path), |
370 base::Bind(&RunGetReservedPathCallback, | 370 base::Bind(&RunGetReservedPathCallback, |
371 callback, | 371 callback, |
372 base::Owned(reserved_path))); | 372 base::Owned(reserved_path))); |
373 } | 373 } |
374 | 374 |
375 // static | 375 // static |
376 bool DownloadPathReservationTracker::IsPathInUseForTesting( | 376 bool DownloadPathReservationTracker::IsPathInUseForTesting( |
377 const base::FilePath& path) { | 377 const base::FilePath& path) { |
378 return IsPathInUse(path); | 378 return IsPathInUse(path); |
379 } | 379 } |
OLD | NEW |