Home | History | Annotate | Download | only in download
      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
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_PATH_RESERVATION_TRACKER_H_
      6 #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_PATH_RESERVATION_TRACKER_H_
      7 
      8 #include "base/callback_forward.h"
      9 
     10 namespace base {
     11 class FilePath;
     12 }
     13 
     14 namespace content {
     15 class DownloadItem;
     16 }
     17 
     18 // Chrome attempts to uniquify filenames that are assigned to downloads in order
     19 // to avoid overwriting files that already exist on the file system. Downloads
     20 // that are considered potentially dangerous use random intermediate filenames.
     21 // Therefore only considering files that exist on the filesystem is
     22 // insufficient. This class tracks files that are assigned to active downloads
     23 // so that uniquification can take those into account as well.
     24 class DownloadPathReservationTracker {
     25  public:
     26   // Callback used with |GetReservedPath|. |target_path| specifies the target
     27   // path for the download. |target_path_verified| is true if all of the
     28   // following is true:
     29   // - |requested_target_path| (passed into GetReservedPath()) was writeable.
     30   // - |target_path| was verified as being unique if uniqueness was
     31   //   required.
     32   //
     33   // If |requested_target_path| was not writeable, then the parent directory of
     34   // |target_path| may be different from that of |requested_target_path|.
     35   typedef base::Callback<void(const base::FilePath& target_path,
     36                               bool target_path_verified)> ReservedPathCallback;
     37 
     38   // The largest index for the uniquification suffix that we will try while
     39   // attempting to come up with a unique path.
     40   static const int kMaxUniqueFiles = 100;
     41 
     42   enum FilenameConflictAction {
     43     UNIQUIFY,
     44     OVERWRITE,
     45     PROMPT,
     46   };
     47 
     48   // When a path needs to be assigned to a download, this method is called on
     49   // the UI thread along with a reference to the download item that will
     50   // eventually receive the reserved path. This method creates a path
     51   // reservation that will live until |download_item| is interrupted, cancelled,
     52   // completes or is removed. This method will not modify |download_item|.
     53   //
     54   // The process of issuing a reservation happens on the FILE thread, and
     55   // involves:
     56   //
     57   // - Creating |requested_target_path.DirName()| if it doesn't already exist
     58   //   and either |create_directory| or |requested_target_path.DirName() ==
     59   //   default_download_path|.
     60   //
     61   // - Verifying that |requested_target_path| is writeable. If not, the user's
     62   //   documents folder is used instead.
     63   //
     64   // - Uniquifying |requested_target_path| by suffixing the filename with a
     65   //   uniquifier (e.g. "foo.txt" -> "foo (1).txt") in order to avoid conflicts
     66   //   with files that already exist on the file system or other download path
     67   //   reservations. Uniquifying is only done if |conflict_action| is UNIQUIFY.
     68   //
     69   // - Posting a task back to the UI thread to invoke |completion_callback| with
     70   //   the reserved path and a bool indicating whether the returned path was
     71   //   verified as being writeable and unique.
     72   //
     73   // In addition, if the target path of |download_item| is changed to a path
     74   // other than the reserved path, then the reservation will be updated to
     75   // match. Such changes can happen if a "Save As" dialog was displayed and the
     76   // user chose a different path. The new target path is not checked against
     77   // active paths to enforce uniqueness. It is only used for uniquifying new
     78   // reservations.
     79   //
     80   // Once |completion_callback| is invoked, it is the caller's responsibility to
     81   // handle cases where the target path could not be verified and set the target
     82   // path of the |download_item| appropriately.
     83   //
     84   // The current implementation doesn't look at symlinks/mount points. E.g.: It
     85   // considers 'foo/bar/x.pdf' and 'foo/baz/x.pdf' to be two different paths,
     86   // even though 'bar' might be a symlink to 'baz'.
     87   static void GetReservedPath(
     88       content::DownloadItem* download_item,
     89       const base::FilePath& requested_target_path,
     90       const base::FilePath& default_download_path,
     91       bool create_directory,
     92       FilenameConflictAction conflict_action,
     93       const ReservedPathCallback& callback);
     94 
     95   // Returns true if |path| is in use by an existing path reservation. Should
     96   // only be called on the FILE thread. Currently only used by tests.
     97   static bool IsPathInUseForTesting(const base::FilePath& path);
     98 };
     99 
    100 #endif  // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_PATH_RESERVATION_TRACKER_H_
    101