Commit c575e745 authored by Min Qin's avatar Min Qin Committed by Commit Bot

Truncate the length of downloaded file name on windows

During annotation, an extra 16 characters(zone identifier)
are appended to the file name.
That may cause the file path to exceed the 260 character limit.
This CL fixes that problem by truncating the file name when generating
it.

BUG=809759

Change-Id: Ie0baa318ccf5824e3ed4df8cf23386653b6747d7
Reviewed-on: https://chromium-review.googlesource.com/919445
Commit-Queue: Min Qin <qinmin@chromium.org>
Reviewed-by: default avatarEric Lawrence <elawrence@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537093}
parent 19591956
...@@ -48,6 +48,12 @@ typedef std::map<ReservationKey, base::FilePath> ReservationMap; ...@@ -48,6 +48,12 @@ typedef std::map<ReservationKey, base::FilePath> ReservationMap;
// possible filename. // possible filename.
const size_t kIntermediateNameSuffixLength = sizeof(".crdownload") - 1; const size_t kIntermediateNameSuffixLength = sizeof(".crdownload") - 1;
#if defined(OS_WIN)
// On windows, zone identifier is appended to the downloaded file name during
// annotation. That increases the length of the final target path.
const size_t kZoneIdentifierLength = sizeof(":Zone.Identifier") - 1;
#endif // defined(OS_WIN)
// Map of download path reservations. Each reserved path is associated with a // Map of download path reservations. Each reserved path is associated with a
// ReservationKey=DownloadItem*. This object is destroyed in |Revoke()| when // ReservationKey=DownloadItem*. This object is destroyed in |Revoke()| when
// there are no more reservations. // there are no more reservations.
...@@ -129,8 +135,15 @@ bool CreateUniqueFilename(int max_path_component_length, base::FilePath* path) { ...@@ -129,8 +135,15 @@ bool CreateUniqueFilename(int max_path_component_length, base::FilePath* path) {
// If the name length limit is available (max_length != -1), and the // If the name length limit is available (max_length != -1), and the
// the current name exceeds the limit, truncate. // the current name exceeds the limit, truncate.
if (max_path_component_length != -1) { if (max_path_component_length != -1) {
#if defined(OS_WIN)
int limit =
max_path_component_length -
std::max(kIntermediateNameSuffixLength, kZoneIdentifierLength) -
suffix.size();
#else
int limit = max_path_component_length - kIntermediateNameSuffixLength - int limit = max_path_component_length - kIntermediateNameSuffixLength -
suffix.size(); suffix.size();
#endif // defined(OS_WIN)
// If truncation failed, give up uniquification. // If truncation failed, give up uniquification.
if (limit <= 0 || if (limit <= 0 ||
!filename_generation::TruncateFilename(&path_to_check, limit)) !filename_generation::TruncateFilename(&path_to_check, limit))
...@@ -178,7 +191,12 @@ PathValidationResult ValidatePathAndResolveConflicts( ...@@ -178,7 +191,12 @@ PathValidationResult ValidatePathAndResolveConflicts(
// Check the limit of file name length if it could be obtained. When the // Check the limit of file name length if it could be obtained. When the
// suggested name exceeds the limit, truncate or prompt the user. // suggested name exceeds the limit, truncate or prompt the user.
if (max_path_component_length != -1) { if (max_path_component_length != -1) {
#if defined(OS_WIN)
int limit = max_path_component_length -
std::max(kIntermediateNameSuffixLength, kZoneIdentifierLength);
#else
int limit = max_path_component_length - kIntermediateNameSuffixLength; int limit = max_path_component_length - kIntermediateNameSuffixLength;
#endif // defined(OS_WIN)
if (limit <= 0 || if (limit <= 0 ||
!filename_generation::TruncateFilename(target_path, limit)) !filename_generation::TruncateFilename(target_path, limit))
return PathValidationResult::NAME_TOO_LONG; return PathValidationResult::NAME_TOO_LONG;
......
...@@ -589,9 +589,13 @@ TEST_F(DownloadPathReservationTrackerTest, BasicTruncation) { ...@@ -589,9 +589,13 @@ TEST_F(DownloadPathReservationTrackerTest, BasicTruncation) {
base::GetMaximumPathComponentLength(default_download_path()); base::GetMaximumPathComponentLength(default_download_path());
ASSERT_NE(-1, real_max_length); ASSERT_NE(-1, real_max_length);
#if defined(OS_WIN)
const size_t max_length = real_max_length - strlen(":Zone.Identifier");
#else
// TODO(kinaba): the current implementation leaves spaces for appending // TODO(kinaba): the current implementation leaves spaces for appending
// ".crdownload". So take it into account. Should be removed in the future. // ".crdownload". So take it into account. Should be removed in the future.
const size_t max_length = real_max_length - 11; const size_t max_length = real_max_length - 11;
#endif // defined(OS_WIN)
std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
base::FilePath path(GetLongNamePathInDownloadsDirectory( base::FilePath path(GetLongNamePathInDownloadsDirectory(
...@@ -618,7 +622,11 @@ TEST_F(DownloadPathReservationTrackerTest, TruncationConflict) { ...@@ -618,7 +622,11 @@ TEST_F(DownloadPathReservationTrackerTest, TruncationConflict) {
int real_max_length = int real_max_length =
base::GetMaximumPathComponentLength(default_download_path()); base::GetMaximumPathComponentLength(default_download_path());
ASSERT_NE(-1, real_max_length); ASSERT_NE(-1, real_max_length);
#if defined(OS_WIN)
const size_t max_length = real_max_length - strlen(":Zone.Identifier");
#else
const size_t max_length = real_max_length - 11; const size_t max_length = real_max_length - 11;
#endif // defined(OS_WIN)
std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
base::FilePath path(GetLongNamePathInDownloadsDirectory( base::FilePath path(GetLongNamePathInDownloadsDirectory(
...@@ -653,7 +661,11 @@ TEST_F(DownloadPathReservationTrackerTest, TruncationFail) { ...@@ -653,7 +661,11 @@ TEST_F(DownloadPathReservationTrackerTest, TruncationFail) {
int real_max_length = int real_max_length =
base::GetMaximumPathComponentLength(default_download_path()); base::GetMaximumPathComponentLength(default_download_path());
ASSERT_NE(-1, real_max_length); ASSERT_NE(-1, real_max_length);
#if defined(OS_WIN)
const size_t max_length = real_max_length - strlen(":Zone.Identifier");
#else
const size_t max_length = real_max_length - 11; const size_t max_length = real_max_length - 11;
#endif // defined(OS_WIN)
std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
base::FilePath path(GetPathInDownloadsDirectory( base::FilePath path(GetPathInDownloadsDirectory(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment