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)#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_PATH_RESERVATION_TRACKER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_PATH_RESERVATION_TRACKER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_forward.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base { 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FilePath; 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadItem; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Chrome attempts to uniquify filenames that are assigned to downloads in order 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// to avoid overwriting files that already exist on the file system. Downloads 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// that are considered potentially dangerous use random intermediate filenames. 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Therefore only considering files that exist on the filesystem is 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// insufficient. This class tracks files that are assigned to active downloads 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// so that uniquification can take those into account as well. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadPathReservationTracker { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callback used with |GetReservedPath|. |target_path| specifies the target 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // path for the download. |target_path_verified| is true if all of the 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // following is true: 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - |requested_target_path| (passed into GetReservedPath()) was writeable. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - |target_path| was verified as being unique if uniqueness was 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // required. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |requested_target_path| was not writeable, then the parent directory of 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |target_path| may be different from that of |requested_target_path|. 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef base::Callback<void(const base::FilePath& target_path, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool target_path_verified)> ReservedPathCallback; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The largest index for the uniquification suffix that we will try while 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // attempting to come up with a unique path. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kMaxUniqueFiles = 100; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) enum FilenameConflictAction { 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UNIQUIFY, 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OVERWRITE, 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PROMPT, 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // When a path needs to be assigned to a download, this method is called on 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the UI thread along with a reference to the download item that will 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // eventually receive the reserved path. This method creates a path 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // reservation that will live until |download_item| is interrupted, cancelled, 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // completes or is removed. This method will not modify |download_item|. 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The process of issuing a reservation happens on the FILE thread, and 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // involves: 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // - Creating |requested_target_path.DirName()| if it doesn't already exist 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // and either |create_directory| or |requested_target_path.DirName() == 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // default_download_path|. 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // - Verifying that |requested_target_path| is writeable. If not, the user's 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // documents folder is used instead. 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // - Uniquifying |requested_target_path| by suffixing the filename with a 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // uniquifier (e.g. "foo.txt" -> "foo (1).txt") in order to avoid conflicts 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // with files that already exist on the file system or other download path 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // reservations. Uniquifying is only done if |conflict_action| is UNIQUIFY. 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // - Posting a task back to the UI thread to invoke |completion_callback| with 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the reserved path and a bool indicating whether the returned path was 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // verified as being writeable and unique. 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // In addition, if the target path of |download_item| is changed to a path 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // other than the reserved path, then the reservation will be updated to 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // match. Such changes can happen if a "Save As" dialog was displayed and the 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // user chose a different path. The new target path is not checked against 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // active paths to enforce uniqueness. It is only used for uniquifying new 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // reservations. 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Once |completion_callback| is invoked, it is the caller's responsibility to 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // handle cases where the target path could not be verified and set the target 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // path of the |download_item| appropriately. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The current implementation doesn't look at symlinks/mount points. E.g.: It 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // considers 'foo/bar/x.pdf' and 'foo/baz/x.pdf' to be two different paths, 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // even though 'bar' might be a symlink to 'baz'. 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static void GetReservedPath( 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content::DownloadItem* download_item, 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& requested_target_path, 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& default_download_path, 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool create_directory, 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FilenameConflictAction conflict_action, 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ReservedPathCallback& callback); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if |path| is in use by an existing path reservation. Should 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only be called on the FILE thread. Currently only used by tests. 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static bool IsPathInUseForTesting(const base::FilePath& path); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_PATH_RESERVATION_TRACKER_H_ 101