| 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 <stddef.h> | 5 #include <stddef.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 | 7 |
| 8 #include <memory> |
| 9 |
| 8 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| 9 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 10 #include "base/files/scoped_temp_dir.h" | 12 #include "base/files/scoped_temp_dir.h" |
| 11 #include "base/memory/weak_ptr.h" | 13 #include "base/memory/weak_ptr.h" |
| 12 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 13 #include "base/observer_list.h" | 15 #include "base/observer_list.h" |
| 14 #include "base/run_loop.h" | 16 #include "base/run_loop.h" |
| 15 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 16 #include "base/test/test_file_util.h" | 18 #include "base/test/test_file_util.h" |
| 17 #include "build/build_config.h" | 19 #include "build/build_config.h" |
| 18 #include "chrome/browser/download/download_path_reservation_tracker.h" | 20 #include "chrome/browser/download/download_path_reservation_tracker.h" |
| 19 #include "chrome/browser/download/download_target_determiner.h" | 21 #include "chrome/browser/download/download_target_determiner.h" |
| 20 #include "chrome/common/features.h" | 22 #include "chrome/common/features.h" |
| 21 #include "content/public/test/mock_download_item.h" | 23 #include "content/public/test/mock_download_item.h" |
| 22 #include "content/public/test/test_browser_thread.h" | 24 #include "content/public/test/test_browser_thread.h" |
| 25 #include "net/base/filename_util.h" |
| 23 #include "testing/gmock/include/gmock/gmock.h" | 26 #include "testing/gmock/include/gmock/gmock.h" |
| 24 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
| 25 | 28 |
| 26 using content::BrowserThread; | 29 using content::BrowserThread; |
| 27 using content::DownloadItem; | 30 using content::DownloadItem; |
| 28 using content::MockDownloadItem; | 31 using content::MockDownloadItem; |
| 29 using testing::AnyNumber; | 32 using testing::AnyNumber; |
| 30 using testing::Return; | 33 using testing::Return; |
| 31 using testing::ReturnRef; | 34 using testing::ReturnRef; |
| 32 using testing::ReturnRefOfCopy; | 35 using testing::ReturnRefOfCopy; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 44 MockDownloadItem* CreateDownloadItem(int32_t id); | 47 MockDownloadItem* CreateDownloadItem(int32_t id); |
| 45 base::FilePath GetPathInDownloadsDirectory( | 48 base::FilePath GetPathInDownloadsDirectory( |
| 46 const base::FilePath::CharType* suffix); | 49 const base::FilePath::CharType* suffix); |
| 47 bool IsPathInUse(const base::FilePath& path); | 50 bool IsPathInUse(const base::FilePath& path); |
| 48 void CallGetReservedPath( | 51 void CallGetReservedPath( |
| 49 DownloadItem* download_item, | 52 DownloadItem* download_item, |
| 50 const base::FilePath& target_path, | 53 const base::FilePath& target_path, |
| 51 bool create_directory, | 54 bool create_directory, |
| 52 DownloadPathReservationTracker::FilenameConflictAction conflict_action, | 55 DownloadPathReservationTracker::FilenameConflictAction conflict_action, |
| 53 base::FilePath* return_path, | 56 base::FilePath* return_path, |
| 54 bool* return_verified); | 57 DownloadTargetResult* return_result); |
| 55 | 58 |
| 56 const base::FilePath& default_download_path() const { | 59 const base::FilePath& default_download_path() const { |
| 57 return default_download_path_; | 60 return default_download_path_; |
| 58 } | 61 } |
| 59 void set_default_download_path(const base::FilePath& path) { | 62 void set_default_download_path(const base::FilePath& path) { |
| 60 default_download_path_ = path; | 63 default_download_path_ = path; |
| 61 } | 64 } |
| 62 // Creates a name of form 'a'*repeat + suffix | 65 // Creates a name of form 'a'*repeat + suffix |
| 63 base::FilePath GetLongNamePathInDownloadsDirectory( | 66 base::FilePath GetLongNamePathInDownloadsDirectory( |
| 64 size_t repeat, const base::FilePath::CharType* suffix); | 67 size_t repeat, |
| 68 const base::FilePath::CharType* suffix); |
| 65 | 69 |
| 66 protected: | 70 protected: |
| 67 base::ScopedTempDir test_download_dir_; | 71 base::ScopedTempDir test_download_dir_; |
| 68 base::FilePath default_download_path_; | 72 base::FilePath default_download_path_; |
| 69 base::MessageLoopForUI message_loop_; | 73 base::MessageLoopForUI message_loop_; |
| 70 content::TestBrowserThread ui_thread_; | 74 content::TestBrowserThread ui_thread_; |
| 71 content::TestBrowserThread file_thread_; | 75 content::TestBrowserThread file_thread_; |
| 72 | 76 |
| 73 private: | 77 private: |
| 74 void TestReservedPathCallback(base::FilePath* return_path, | 78 void TestReservedPathCallback(base::FilePath* return_path, |
| 75 bool* return_verified, bool* did_run_callback, | 79 DownloadTargetResult* return_result, |
| 76 const base::FilePath& path, bool verified); | 80 const base::Closure& quit_closure, |
| 81 const base::FilePath& path, |
| 82 DownloadTargetResult result); |
| 77 }; | 83 }; |
| 78 | 84 |
| 79 DownloadPathReservationTrackerTest::DownloadPathReservationTrackerTest() | 85 DownloadPathReservationTrackerTest::DownloadPathReservationTrackerTest() |
| 80 : ui_thread_(BrowserThread::UI, &message_loop_), | 86 : ui_thread_(BrowserThread::UI, &message_loop_), |
| 81 file_thread_(BrowserThread::FILE, &message_loop_) { | 87 file_thread_(BrowserThread::FILE, &message_loop_) { |
| 82 } | 88 } |
| 83 | 89 |
| 84 void DownloadPathReservationTrackerTest::SetUp() { | 90 void DownloadPathReservationTrackerTest::SetUp() { |
| 85 ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir()); | 91 ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir()); |
| 86 set_default_download_path(test_download_dir_.GetPath()); | 92 set_default_download_path(test_download_dir_.GetPath()); |
| 87 } | 93 } |
| 88 | 94 |
| 89 void DownloadPathReservationTrackerTest::TearDown() { | 95 void DownloadPathReservationTrackerTest::TearDown() { |
| 90 base::RunLoop().RunUntilIdle(); | 96 base::RunLoop().RunUntilIdle(); |
| 91 } | 97 } |
| 92 | 98 |
| 93 MockDownloadItem* DownloadPathReservationTrackerTest::CreateDownloadItem( | 99 MockDownloadItem* DownloadPathReservationTrackerTest::CreateDownloadItem( |
| 94 int32_t id) { | 100 int32_t id) { |
| 95 MockDownloadItem* item = new ::testing::StrictMock<MockDownloadItem>; | 101 MockDownloadItem* item = new ::testing::StrictMock<MockDownloadItem>; |
| 96 EXPECT_CALL(*item, GetId()) | 102 EXPECT_CALL(*item, GetId()) |
| 97 .WillRepeatedly(Return(id)); | 103 .WillRepeatedly(Return(id)); |
| 98 EXPECT_CALL(*item, GetTargetFilePath()) | 104 EXPECT_CALL(*item, GetTargetFilePath()) |
| 99 .WillRepeatedly(ReturnRefOfCopy(base::FilePath())); | 105 .WillRepeatedly(ReturnRefOfCopy(base::FilePath())); |
| 100 EXPECT_CALL(*item, GetState()) | 106 EXPECT_CALL(*item, GetState()) |
| 101 .WillRepeatedly(Return(DownloadItem::IN_PROGRESS)); | 107 .WillRepeatedly(Return(DownloadItem::IN_PROGRESS)); |
| 108 EXPECT_CALL(*item, GetURL()).WillRepeatedly(ReturnRefOfCopy(GURL())); |
| 102 return item; | 109 return item; |
| 103 } | 110 } |
| 104 | 111 |
| 105 base::FilePath DownloadPathReservationTrackerTest::GetPathInDownloadsDirectory( | 112 base::FilePath DownloadPathReservationTrackerTest::GetPathInDownloadsDirectory( |
| 106 const base::FilePath::CharType* suffix) { | 113 const base::FilePath::CharType* suffix) { |
| 107 return default_download_path().Append(suffix).NormalizePathSeparators(); | 114 return default_download_path().Append(suffix).NormalizePathSeparators(); |
| 108 } | 115 } |
| 109 | 116 |
| 110 bool DownloadPathReservationTrackerTest::IsPathInUse( | 117 bool DownloadPathReservationTrackerTest::IsPathInUse( |
| 111 const base::FilePath& path) { | 118 const base::FilePath& path) { |
| 112 return DownloadPathReservationTracker::IsPathInUseForTesting(path); | 119 return DownloadPathReservationTracker::IsPathInUseForTesting(path); |
| 113 } | 120 } |
| 114 | 121 |
| 115 void DownloadPathReservationTrackerTest::CallGetReservedPath( | 122 void DownloadPathReservationTrackerTest::CallGetReservedPath( |
| 116 DownloadItem* download_item, | 123 DownloadItem* download_item, |
| 117 const base::FilePath& target_path, | 124 const base::FilePath& target_path, |
| 118 bool create_directory, | 125 bool create_directory, |
| 119 DownloadPathReservationTracker::FilenameConflictAction conflict_action, | 126 DownloadPathReservationTracker::FilenameConflictAction conflict_action, |
| 120 base::FilePath* return_path, | 127 base::FilePath* return_path, |
| 121 bool* return_verified) { | 128 DownloadTargetResult* return_result) { |
| 122 // Weak pointer factory to prevent the callback from running after this | 129 // Weak pointer factory to prevent the callback from running after this |
| 123 // function has returned. | 130 // function has returned. |
| 124 base::WeakPtrFactory<DownloadPathReservationTrackerTest> weak_ptr_factory( | 131 base::WeakPtrFactory<DownloadPathReservationTrackerTest> weak_ptr_factory( |
| 125 this); | 132 this); |
| 126 bool did_run_callback = false; | 133 base::RunLoop run_loop; |
| 127 DownloadPathReservationTracker::GetReservedPath( | 134 DownloadPathReservationTracker::GetReservedPath( |
| 128 download_item, | 135 download_item, target_path, default_download_path(), create_directory, |
| 129 target_path, | |
| 130 default_download_path(), | |
| 131 create_directory, | |
| 132 conflict_action, | 136 conflict_action, |
| 133 base::Bind(&DownloadPathReservationTrackerTest::TestReservedPathCallback, | 137 base::Bind(&DownloadPathReservationTrackerTest::TestReservedPathCallback, |
| 134 weak_ptr_factory.GetWeakPtr(), return_path, return_verified, | 138 weak_ptr_factory.GetWeakPtr(), return_path, return_result, |
| 135 &did_run_callback)); | 139 run_loop.QuitClosure())); |
| 136 base::RunLoop().RunUntilIdle(); | 140 run_loop.Run(); |
| 137 EXPECT_TRUE(did_run_callback); | |
| 138 } | 141 } |
| 139 | 142 |
| 140 void DownloadPathReservationTrackerTest::TestReservedPathCallback( | 143 void DownloadPathReservationTrackerTest::TestReservedPathCallback( |
| 141 base::FilePath* return_path, bool* return_verified, bool* did_run_callback, | 144 base::FilePath* return_path, |
| 142 const base::FilePath& path, bool verified) { | 145 DownloadTargetResult* return_result, |
| 143 *did_run_callback = true; | 146 const base::Closure& quit_closure, |
| 147 const base::FilePath& path, |
| 148 DownloadTargetResult result) { |
| 144 *return_path = path; | 149 *return_path = path; |
| 145 *return_verified = verified; | 150 *return_result = result; |
| 151 quit_closure.Run(); |
| 146 } | 152 } |
| 147 | 153 |
| 148 base::FilePath | 154 base::FilePath |
| 149 DownloadPathReservationTrackerTest::GetLongNamePathInDownloadsDirectory( | 155 DownloadPathReservationTrackerTest::GetLongNamePathInDownloadsDirectory( |
| 150 size_t repeat, const base::FilePath::CharType* suffix) { | 156 size_t repeat, const base::FilePath::CharType* suffix) { |
| 151 return GetPathInDownloadsDirectory( | 157 return GetPathInDownloadsDirectory( |
| 152 (base::FilePath::StringType(repeat, FILE_PATH_LITERAL('a')) | 158 (base::FilePath::StringType(repeat, FILE_PATH_LITERAL('a')) |
| 153 + suffix).c_str()); | 159 + suffix).c_str()); |
| 154 } | 160 } |
| 155 | 161 |
| 156 void SetDownloadItemState(content::MockDownloadItem* download_item, | 162 void SetDownloadItemState(content::MockDownloadItem* download_item, |
| 157 content::DownloadItem::DownloadState state) { | 163 content::DownloadItem::DownloadState state) { |
| 158 EXPECT_CALL(*download_item, GetState()) | 164 EXPECT_CALL(*download_item, GetState()) |
| 159 .WillRepeatedly(Return(state)); | 165 .WillRepeatedly(Return(state)); |
| 160 download_item->NotifyObserversDownloadUpdated(); | 166 download_item->NotifyObserversDownloadUpdated(); |
| 161 } | 167 } |
| 162 | 168 |
| 163 } // namespace | 169 } // namespace |
| 164 | 170 |
| 165 // A basic reservation is acquired and committed. | 171 // A basic reservation is acquired and committed. |
| 166 TEST_F(DownloadPathReservationTrackerTest, BasicReservation) { | 172 TEST_F(DownloadPathReservationTrackerTest, BasicReservation) { |
| 167 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); | 173 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); |
| 168 base::FilePath path( | 174 base::FilePath path( |
| 169 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); | 175 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); |
| 170 ASSERT_FALSE(IsPathInUse(path)); | 176 ASSERT_FALSE(IsPathInUse(path)); |
| 171 | 177 |
| 172 base::FilePath reserved_path; | 178 base::FilePath reserved_path; |
| 173 bool verified = false; | 179 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 174 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 180 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 175 DownloadPathReservationTracker::OVERWRITE; | 181 DownloadPathReservationTracker::OVERWRITE; |
| 176 bool create_directory = false; | 182 bool create_directory = false; |
| 177 CallGetReservedPath( | 183 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 178 item.get(), | 184 &reserved_path, &result); |
| 179 path, | |
| 180 create_directory, | |
| 181 conflict_action, | |
| 182 &reserved_path, | |
| 183 &verified); | |
| 184 EXPECT_TRUE(IsPathInUse(path)); | 185 EXPECT_TRUE(IsPathInUse(path)); |
| 185 EXPECT_TRUE(verified); | 186 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 186 EXPECT_EQ(path.value(), reserved_path.value()); | 187 EXPECT_EQ(path.value(), reserved_path.value()); |
| 187 | 188 |
| 188 // Destroying the item should release the reservation. | 189 // Destroying the item should release the reservation. |
| 189 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); | 190 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); |
| 190 item.reset(); | 191 item.reset(); |
| 191 base::RunLoop().RunUntilIdle(); | 192 base::RunLoop().RunUntilIdle(); |
| 192 EXPECT_FALSE(IsPathInUse(path)); | 193 EXPECT_FALSE(IsPathInUse(path)); |
| 193 } | 194 } |
| 194 | 195 |
| 195 // A download that is interrupted should lose its reservation. | 196 // A download that is interrupted should lose its reservation. |
| 196 TEST_F(DownloadPathReservationTrackerTest, InterruptedDownload) { | 197 TEST_F(DownloadPathReservationTrackerTest, InterruptedDownload) { |
| 197 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); | 198 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); |
| 198 base::FilePath path( | 199 base::FilePath path( |
| 199 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); | 200 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); |
| 200 ASSERT_FALSE(IsPathInUse(path)); | 201 ASSERT_FALSE(IsPathInUse(path)); |
| 201 | 202 |
| 202 base::FilePath reserved_path; | 203 base::FilePath reserved_path; |
| 203 bool verified = false; | 204 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 204 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 205 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 205 DownloadPathReservationTracker::OVERWRITE; | 206 DownloadPathReservationTracker::OVERWRITE; |
| 206 bool create_directory = false; | 207 bool create_directory = false; |
| 207 CallGetReservedPath( | 208 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 208 item.get(), | 209 &reserved_path, &result); |
| 209 path, | |
| 210 create_directory, | |
| 211 conflict_action, | |
| 212 &reserved_path, | |
| 213 &verified); | |
| 214 EXPECT_TRUE(IsPathInUse(path)); | 210 EXPECT_TRUE(IsPathInUse(path)); |
| 215 EXPECT_TRUE(verified); | 211 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 216 EXPECT_EQ(path.value(), reserved_path.value()); | 212 EXPECT_EQ(path.value(), reserved_path.value()); |
| 217 | 213 |
| 218 // Once the download is interrupted, the path should become available again. | 214 // Once the download is interrupted, the path should become available again. |
| 219 SetDownloadItemState(item.get(), DownloadItem::INTERRUPTED); | 215 SetDownloadItemState(item.get(), DownloadItem::INTERRUPTED); |
| 220 base::RunLoop().RunUntilIdle(); | 216 base::RunLoop().RunUntilIdle(); |
| 221 EXPECT_FALSE(IsPathInUse(path)); | 217 EXPECT_FALSE(IsPathInUse(path)); |
| 222 } | 218 } |
| 223 | 219 |
| 224 // A completed download should also lose its reservation. | 220 // A completed download should also lose its reservation. |
| 225 TEST_F(DownloadPathReservationTrackerTest, CompleteDownload) { | 221 TEST_F(DownloadPathReservationTrackerTest, CompleteDownload) { |
| 226 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); | 222 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); |
| 227 base::FilePath path( | 223 base::FilePath path( |
| 228 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); | 224 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); |
| 229 ASSERT_FALSE(IsPathInUse(path)); | 225 ASSERT_FALSE(IsPathInUse(path)); |
| 230 | 226 |
| 231 base::FilePath reserved_path; | 227 base::FilePath reserved_path; |
| 232 bool verified = false; | 228 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 233 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 229 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 234 DownloadPathReservationTracker::OVERWRITE; | 230 DownloadPathReservationTracker::OVERWRITE; |
| 235 bool create_directory = false; | 231 bool create_directory = false; |
| 236 CallGetReservedPath( | 232 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 237 item.get(), | 233 &reserved_path, &result); |
| 238 path, | |
| 239 create_directory, | |
| 240 conflict_action, | |
| 241 &reserved_path, | |
| 242 &verified); | |
| 243 EXPECT_TRUE(IsPathInUse(path)); | 234 EXPECT_TRUE(IsPathInUse(path)); |
| 244 EXPECT_TRUE(verified); | 235 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 245 EXPECT_EQ(path.value(), reserved_path.value()); | 236 EXPECT_EQ(path.value(), reserved_path.value()); |
| 246 | 237 |
| 247 // Once the download completes, the path should become available again. For a | 238 // Once the download completes, the path should become available again. For a |
| 248 // real download, at this point only the path reservation will be released. | 239 // real download, at this point only the path reservation will be released. |
| 249 // The path wouldn't be available since it is occupied on disk by the | 240 // The path wouldn't be available since it is occupied on disk by the |
| 250 // completed download. | 241 // completed download. |
| 251 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); | 242 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); |
| 252 base::RunLoop().RunUntilIdle(); | 243 base::RunLoop().RunUntilIdle(); |
| 253 EXPECT_FALSE(IsPathInUse(path)); | 244 EXPECT_FALSE(IsPathInUse(path)); |
| 254 } | 245 } |
| 255 | 246 |
| 256 // If there are files on the file system, a unique reservation should uniquify | 247 // If there are files on the file system, a unique reservation should uniquify |
| 257 // around it. | 248 // around it. |
| 258 TEST_F(DownloadPathReservationTrackerTest, ConflictingFiles) { | 249 TEST_F(DownloadPathReservationTrackerTest, ConflictingFiles) { |
| 259 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); | 250 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); |
| 260 base::FilePath path( | 251 base::FilePath path( |
| 261 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); | 252 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); |
| 262 base::FilePath path1( | 253 base::FilePath path1( |
| 263 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt"))); | 254 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt"))); |
| 264 // Create a file at |path|, and a .crdownload file at |path1|. | 255 // Create a file at |path|, and a .crdownload file at |path1|. |
| 265 ASSERT_EQ(0, base::WriteFile(path, "", 0)); | 256 ASSERT_EQ(0, base::WriteFile(path, "", 0)); |
| 266 ASSERT_EQ(0, | 257 ASSERT_EQ(0, |
| 267 base::WriteFile( | 258 base::WriteFile( |
| 268 DownloadTargetDeterminer::GetCrDownloadPath(path1), "", 0)); | 259 DownloadTargetDeterminer::GetCrDownloadPath(path1), "", 0)); |
| 269 ASSERT_TRUE(IsPathInUse(path)); | 260 ASSERT_TRUE(IsPathInUse(path)); |
| 270 | 261 |
| 271 base::FilePath reserved_path; | 262 base::FilePath reserved_path; |
| 272 bool verified = false; | 263 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 273 bool create_directory = false; | 264 bool create_directory = false; |
| 274 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 265 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 275 DownloadPathReservationTracker::UNIQUIFY; | 266 DownloadPathReservationTracker::UNIQUIFY; |
| 276 CallGetReservedPath( | 267 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 277 item.get(), | 268 &reserved_path, &result); |
| 278 path, | |
| 279 create_directory, | |
| 280 conflict_action, | |
| 281 &reserved_path, | |
| 282 &verified); | |
| 283 EXPECT_TRUE(IsPathInUse(path)); | 269 EXPECT_TRUE(IsPathInUse(path)); |
| 284 EXPECT_TRUE(IsPathInUse(reserved_path)); | 270 EXPECT_TRUE(IsPathInUse(reserved_path)); |
| 285 EXPECT_TRUE(verified); | 271 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 286 // The path should be uniquified, skipping over foo.txt but not over | 272 // The path should be uniquified, skipping over foo.txt but not over |
| 287 // "foo (1).txt.crdownload" | 273 // "foo (1).txt.crdownload" |
| 288 EXPECT_EQ( | 274 EXPECT_EQ( |
| 289 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")).value(), | 275 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")).value(), |
| 290 reserved_path.value()); | 276 reserved_path.value()); |
| 291 | 277 |
| 292 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); | 278 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); |
| 293 item.reset(); | 279 item.reset(); |
| 294 base::RunLoop().RunUntilIdle(); | 280 base::RunLoop().RunUntilIdle(); |
| 295 EXPECT_TRUE(IsPathInUse(path)); | 281 EXPECT_TRUE(IsPathInUse(path)); |
| 296 EXPECT_FALSE(IsPathInUse(reserved_path)); | 282 EXPECT_FALSE(IsPathInUse(reserved_path)); |
| 297 } | 283 } |
| 298 | 284 |
| 285 // If there are conflicting files on the file system, an overwriting reservation |
| 286 // should succeed without altering the target path. |
| 287 TEST_F(DownloadPathReservationTrackerTest, ConflictingFiles_Overwrite) { |
| 288 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); |
| 289 base::FilePath path( |
| 290 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); |
| 291 // Create a file at |path|. |
| 292 ASSERT_EQ(0, base::WriteFile(path, "", 0)); |
| 293 ASSERT_TRUE(IsPathInUse(path)); |
| 294 |
| 295 base::FilePath reserved_path; |
| 296 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 297 bool create_directory = false; |
| 298 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 299 DownloadPathReservationTracker::OVERWRITE; |
| 300 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 301 &reserved_path, &result); |
| 302 EXPECT_TRUE(IsPathInUse(path)); |
| 303 EXPECT_TRUE(IsPathInUse(reserved_path)); |
| 304 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 305 EXPECT_EQ(path.value(), reserved_path.value()); |
| 306 |
| 307 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); |
| 308 item.reset(); |
| 309 base::RunLoop().RunUntilIdle(); |
| 310 } |
| 311 |
| 299 // Multiple reservations for the same path should uniquify around each other. | 312 // Multiple reservations for the same path should uniquify around each other. |
| 300 TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) { | 313 TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) { |
| 301 std::unique_ptr<MockDownloadItem> item1(CreateDownloadItem(1)); | 314 std::unique_ptr<MockDownloadItem> item1(CreateDownloadItem(1)); |
| 302 base::FilePath path( | 315 base::FilePath path( |
| 303 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); | 316 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); |
| 304 base::FilePath uniquified_path( | 317 base::FilePath uniquified_path( |
| 305 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt"))); | 318 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt"))); |
| 306 ASSERT_FALSE(IsPathInUse(path)); | 319 ASSERT_FALSE(IsPathInUse(path)); |
| 307 ASSERT_FALSE(IsPathInUse(uniquified_path)); | 320 ASSERT_FALSE(IsPathInUse(uniquified_path)); |
| 308 | 321 |
| 309 base::FilePath reserved_path1; | 322 base::FilePath reserved_path1; |
| 310 bool verified = false; | 323 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 311 bool create_directory = false; | 324 bool create_directory = false; |
| 312 | 325 |
| 313 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 326 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 314 DownloadPathReservationTracker::UNIQUIFY; | 327 DownloadPathReservationTracker::UNIQUIFY; |
| 315 CallGetReservedPath( | 328 CallGetReservedPath(item1.get(), path, create_directory, conflict_action, |
| 316 item1.get(), | 329 &reserved_path1, &result); |
| 317 path, | |
| 318 create_directory, | |
| 319 conflict_action, | |
| 320 &reserved_path1, | |
| 321 &verified); | |
| 322 EXPECT_TRUE(IsPathInUse(path)); | 330 EXPECT_TRUE(IsPathInUse(path)); |
| 323 EXPECT_TRUE(verified); | 331 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 324 | |
| 325 | 332 |
| 326 { | 333 { |
| 327 // Requesting a reservation for the same path with uniquification results in | 334 // Requesting a reservation for the same path with uniquification results in |
| 328 // a uniquified path. | 335 // a uniquified path. |
| 329 std::unique_ptr<MockDownloadItem> item2(CreateDownloadItem(2)); | 336 std::unique_ptr<MockDownloadItem> item2(CreateDownloadItem(2)); |
| 330 base::FilePath reserved_path2; | 337 base::FilePath reserved_path2; |
| 331 CallGetReservedPath( | 338 CallGetReservedPath(item2.get(), path, create_directory, conflict_action, |
| 332 item2.get(), | 339 &reserved_path2, &result); |
| 333 path, | |
| 334 create_directory, | |
| 335 conflict_action, | |
| 336 &reserved_path2, | |
| 337 &verified); | |
| 338 EXPECT_TRUE(IsPathInUse(path)); | 340 EXPECT_TRUE(IsPathInUse(path)); |
| 339 EXPECT_TRUE(IsPathInUse(uniquified_path)); | 341 EXPECT_TRUE(IsPathInUse(uniquified_path)); |
| 340 EXPECT_EQ(uniquified_path.value(), reserved_path2.value()); | 342 EXPECT_EQ(uniquified_path.value(), reserved_path2.value()); |
| 341 SetDownloadItemState(item2.get(), DownloadItem::COMPLETE); | 343 SetDownloadItemState(item2.get(), DownloadItem::COMPLETE); |
| 342 } | 344 } |
| 343 base::RunLoop().RunUntilIdle(); | 345 base::RunLoop().RunUntilIdle(); |
| 344 EXPECT_TRUE(IsPathInUse(path)); | 346 EXPECT_TRUE(IsPathInUse(path)); |
| 345 EXPECT_FALSE(IsPathInUse(uniquified_path)); | 347 EXPECT_FALSE(IsPathInUse(uniquified_path)); |
| 346 | 348 |
| 347 { | 349 { |
| 348 // Since the previous download item was removed, requesting a reservation | 350 // Since the previous download item was removed, requesting a reservation |
| 349 // for the same path should result in the same uniquified path. | 351 // for the same path should result in the same uniquified path. |
| 350 std::unique_ptr<MockDownloadItem> item2(CreateDownloadItem(2)); | 352 std::unique_ptr<MockDownloadItem> item2(CreateDownloadItem(2)); |
| 351 base::FilePath reserved_path2; | 353 base::FilePath reserved_path2; |
| 352 CallGetReservedPath( | 354 CallGetReservedPath(item2.get(), path, create_directory, conflict_action, |
| 353 item2.get(), | 355 &reserved_path2, &result); |
| 354 path, | |
| 355 create_directory, | |
| 356 conflict_action, | |
| 357 &reserved_path2, | |
| 358 &verified); | |
| 359 EXPECT_TRUE(IsPathInUse(path)); | 356 EXPECT_TRUE(IsPathInUse(path)); |
| 360 EXPECT_TRUE(IsPathInUse(uniquified_path)); | 357 EXPECT_TRUE(IsPathInUse(uniquified_path)); |
| 361 EXPECT_EQ(uniquified_path.value(), reserved_path2.value()); | 358 EXPECT_EQ(uniquified_path.value(), reserved_path2.value()); |
| 362 SetDownloadItemState(item2.get(), DownloadItem::COMPLETE); | 359 SetDownloadItemState(item2.get(), DownloadItem::COMPLETE); |
| 363 } | 360 } |
| 364 base::RunLoop().RunUntilIdle(); | 361 base::RunLoop().RunUntilIdle(); |
| 365 | 362 |
| 366 // Now acquire an overwriting reservation. We should end up with the same | 363 // Now acquire an overwriting reservation. We should end up with the same |
| 367 // non-uniquified path for both reservations. | 364 // non-uniquified path for both reservations. |
| 368 std::unique_ptr<MockDownloadItem> item3(CreateDownloadItem(2)); | 365 std::unique_ptr<MockDownloadItem> item3(CreateDownloadItem(2)); |
| 369 base::FilePath reserved_path3; | 366 base::FilePath reserved_path3; |
| 370 conflict_action = DownloadPathReservationTracker::OVERWRITE; | 367 conflict_action = DownloadPathReservationTracker::OVERWRITE; |
| 371 CallGetReservedPath( | 368 CallGetReservedPath(item3.get(), path, create_directory, conflict_action, |
| 372 item3.get(), | 369 &reserved_path3, &result); |
| 373 path, | |
| 374 create_directory, | |
| 375 conflict_action, | |
| 376 &reserved_path3, | |
| 377 &verified); | |
| 378 EXPECT_TRUE(IsPathInUse(path)); | 370 EXPECT_TRUE(IsPathInUse(path)); |
| 379 EXPECT_FALSE(IsPathInUse(uniquified_path)); | 371 EXPECT_FALSE(IsPathInUse(uniquified_path)); |
| 380 | 372 |
| 381 EXPECT_EQ(path.value(), reserved_path1.value()); | 373 EXPECT_EQ(path.value(), reserved_path1.value()); |
| 382 EXPECT_EQ(path.value(), reserved_path3.value()); | 374 EXPECT_EQ(path.value(), reserved_path3.value()); |
| 383 | 375 |
| 384 SetDownloadItemState(item1.get(), DownloadItem::COMPLETE); | 376 SetDownloadItemState(item1.get(), DownloadItem::COMPLETE); |
| 385 SetDownloadItemState(item3.get(), DownloadItem::COMPLETE); | 377 SetDownloadItemState(item3.get(), DownloadItem::COMPLETE); |
| 386 } | 378 } |
| 387 | 379 |
| 388 // Two active downloads shouldn't be able to reserve paths that only differ by | 380 // Two active downloads shouldn't be able to reserve paths that only differ by |
| 389 // case. | 381 // case. |
| 390 TEST_F(DownloadPathReservationTrackerTest, ConflictingCaseReservations) { | 382 TEST_F(DownloadPathReservationTrackerTest, ConflictingCaseReservations) { |
| 391 std::unique_ptr<MockDownloadItem> item1(CreateDownloadItem(1)); | 383 std::unique_ptr<MockDownloadItem> item1(CreateDownloadItem(1)); |
| 392 std::unique_ptr<MockDownloadItem> item2(CreateDownloadItem(2)); | 384 std::unique_ptr<MockDownloadItem> item2(CreateDownloadItem(2)); |
| 393 | 385 |
| 394 base::FilePath path_foo = | 386 base::FilePath path_foo = |
| 395 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")); | 387 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")); |
| 396 base::FilePath path_Foo = | 388 base::FilePath path_Foo = |
| 397 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("Foo.txt")); | 389 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("Foo.txt")); |
| 398 | 390 |
| 399 base::FilePath first_reservation; | 391 base::FilePath first_reservation; |
| 400 bool verified = false; | 392 DownloadTargetResult result = DownloadTargetResult::PATH_NOT_WRITEABLE; |
| 401 CallGetReservedPath(item1.get(), path_foo, false, | 393 CallGetReservedPath(item1.get(), path_foo, false, |
| 402 DownloadPathReservationTracker::UNIQUIFY, | 394 DownloadPathReservationTracker::UNIQUIFY, |
| 403 &first_reservation, &verified); | 395 &first_reservation, &result); |
| 404 EXPECT_TRUE(IsPathInUse(path_foo)); | 396 EXPECT_TRUE(IsPathInUse(path_foo)); |
| 405 EXPECT_TRUE(verified); | 397 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 406 EXPECT_EQ(path_foo, first_reservation); | 398 EXPECT_EQ(path_foo, first_reservation); |
| 407 | 399 |
| 408 // Foo should also be in use at this point. | 400 // Foo should also be in use at this point. |
| 409 EXPECT_TRUE(IsPathInUse(path_Foo)); | 401 EXPECT_TRUE(IsPathInUse(path_Foo)); |
| 410 | 402 |
| 411 base::FilePath second_reservation; | 403 base::FilePath second_reservation; |
| 412 CallGetReservedPath(item2.get(), path_Foo, false, | 404 CallGetReservedPath(item2.get(), path_Foo, false, |
| 413 DownloadPathReservationTracker::UNIQUIFY, | 405 DownloadPathReservationTracker::UNIQUIFY, |
| 414 &second_reservation, &verified); | 406 &second_reservation, &result); |
| 415 EXPECT_TRUE(verified); | 407 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 416 EXPECT_EQ(GetPathInDownloadsDirectory(FILE_PATH_LITERAL("Foo (1).txt")), | 408 EXPECT_EQ(GetPathInDownloadsDirectory(FILE_PATH_LITERAL("Foo (1).txt")), |
| 417 second_reservation); | 409 second_reservation); |
| 418 SetDownloadItemState(item1.get(), DownloadItem::COMPLETE); | 410 SetDownloadItemState(item1.get(), DownloadItem::COMPLETE); |
| 419 SetDownloadItemState(item2.get(), DownloadItem::COMPLETE); | 411 SetDownloadItemState(item2.get(), DownloadItem::COMPLETE); |
| 420 } | 412 } |
| 421 | 413 |
| 422 // If a unique path cannot be determined after trying kMaxUniqueFiles | 414 // If a unique path cannot be determined after trying kMaxUniqueFiles |
| 423 // uniquifiers, then the callback should notified that verification failed, and | 415 // uniquifiers, then the callback should notified that verification failed, and |
| 424 // the returned path should be set to the original requested path. | 416 // the returned path should be set to the original requested path. |
| 425 TEST_F(DownloadPathReservationTrackerTest, UnresolvedConflicts) { | 417 TEST_F(DownloadPathReservationTrackerTest, UnresolvedConflicts) { |
| 426 base::FilePath path( | 418 base::FilePath path( |
| 427 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); | 419 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); |
| 428 std::unique_ptr<MockDownloadItem> | 420 std::unique_ptr<MockDownloadItem> |
| 429 items[DownloadPathReservationTracker::kMaxUniqueFiles + 1]; | 421 items[DownloadPathReservationTracker::kMaxUniqueFiles + 1]; |
| 430 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 422 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 431 DownloadPathReservationTracker::UNIQUIFY; | 423 DownloadPathReservationTracker::UNIQUIFY; |
| 432 bool create_directory = false; | 424 bool create_directory = false; |
| 433 | 425 |
| 434 // Create |kMaxUniqueFiles + 1| reservations for |path|. The first reservation | 426 // Create |kMaxUniqueFiles + 1| reservations for |path|. The first reservation |
| 435 // will have no uniquifier. The |kMaxUniqueFiles| remaining reservations do. | 427 // will have no uniquifier. The |kMaxUniqueFiles| remaining reservations do. |
| 436 for (int i = 0; i <= DownloadPathReservationTracker::kMaxUniqueFiles; i++) { | 428 for (int i = 0; i <= DownloadPathReservationTracker::kMaxUniqueFiles; i++) { |
| 437 base::FilePath reserved_path; | 429 base::FilePath reserved_path; |
| 438 base::FilePath expected_path; | 430 base::FilePath expected_path; |
| 439 bool verified = false; | 431 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 440 if (i > 0) { | 432 if (i > 0) { |
| 441 expected_path = | 433 expected_path = |
| 442 path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", i)); | 434 path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", i)); |
| 443 } else { | 435 } else { |
| 444 expected_path = path; | 436 expected_path = path; |
| 445 } | 437 } |
| 446 items[i].reset(CreateDownloadItem(i)); | 438 items[i].reset(CreateDownloadItem(i)); |
| 447 EXPECT_FALSE(IsPathInUse(expected_path)); | 439 EXPECT_FALSE(IsPathInUse(expected_path)); |
| 448 CallGetReservedPath( | 440 CallGetReservedPath(items[i].get(), path, create_directory, conflict_action, |
| 449 items[i].get(), | 441 &reserved_path, &result); |
| 450 path, | |
| 451 create_directory, | |
| 452 conflict_action, | |
| 453 &reserved_path, | |
| 454 &verified); | |
| 455 EXPECT_TRUE(IsPathInUse(expected_path)); | 442 EXPECT_TRUE(IsPathInUse(expected_path)); |
| 456 EXPECT_EQ(expected_path.value(), reserved_path.value()); | 443 EXPECT_EQ(expected_path.value(), reserved_path.value()); |
| 457 EXPECT_TRUE(verified); | 444 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 458 } | 445 } |
| 459 // The next reservation for |path| will fail to be unique. | 446 // The next reservation for |path| will fail to be unique. |
| 460 std::unique_ptr<MockDownloadItem> item( | 447 std::unique_ptr<MockDownloadItem> item( |
| 461 CreateDownloadItem(DownloadPathReservationTracker::kMaxUniqueFiles + 1)); | 448 CreateDownloadItem(DownloadPathReservationTracker::kMaxUniqueFiles + 1)); |
| 462 base::FilePath reserved_path; | 449 base::FilePath reserved_path; |
| 463 bool verified = true; | 450 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 464 CallGetReservedPath( | 451 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 465 item.get(), | 452 &reserved_path, &result); |
| 466 path, | 453 EXPECT_EQ(DownloadTargetResult::CONFLICT, result); |
| 467 create_directory, | |
| 468 conflict_action, | |
| 469 &reserved_path, | |
| 470 &verified); | |
| 471 EXPECT_FALSE(verified); | |
| 472 EXPECT_EQ(path.value(), reserved_path.value()); | 454 EXPECT_EQ(path.value(), reserved_path.value()); |
| 473 | 455 |
| 474 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); | 456 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); |
| 475 for (int i = 0; i <= DownloadPathReservationTracker::kMaxUniqueFiles; i++) | 457 for (int i = 0; i <= DownloadPathReservationTracker::kMaxUniqueFiles; i++) |
| 476 SetDownloadItemState(items[i].get(), DownloadItem::COMPLETE); | 458 SetDownloadItemState(items[i].get(), DownloadItem::COMPLETE); |
| 477 } | 459 } |
| 478 | 460 |
| 479 // If the target directory is unwriteable, then callback should be notified that | 461 // If the target directory is unwriteable, then callback should be notified that |
| 480 // verification failed. | 462 // verification failed. |
| 481 TEST_F(DownloadPathReservationTrackerTest, UnwriteableDirectory) { | 463 TEST_F(DownloadPathReservationTrackerTest, UnwriteableDirectory) { |
| 482 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); | 464 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); |
| 483 base::FilePath path( | 465 base::FilePath path( |
| 484 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); | 466 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); |
| 485 base::FilePath dir(path.DirName()); | 467 base::FilePath dir(path.DirName()); |
| 486 ASSERT_FALSE(IsPathInUse(path)); | 468 ASSERT_FALSE(IsPathInUse(path)); |
| 487 | 469 |
| 488 { | 470 { |
| 489 // Scope for FilePermissionRestorer | 471 // Scope for FilePermissionRestorer |
| 490 base::FilePermissionRestorer restorer(dir); | 472 base::FilePermissionRestorer restorer(dir); |
| 491 EXPECT_TRUE(base::MakeFileUnwritable(dir)); | 473 EXPECT_TRUE(base::MakeFileUnwritable(dir)); |
| 492 base::FilePath reserved_path; | 474 base::FilePath reserved_path; |
| 493 bool verified = true; | 475 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 494 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 476 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 495 DownloadPathReservationTracker::OVERWRITE; | 477 DownloadPathReservationTracker::OVERWRITE; |
| 496 bool create_directory = false; | 478 bool create_directory = false; |
| 497 CallGetReservedPath( | 479 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 498 item.get(), | 480 &reserved_path, &result); |
| 499 path, | |
| 500 create_directory, | |
| 501 conflict_action, | |
| 502 &reserved_path, | |
| 503 &verified); | |
| 504 // Verification fails. | 481 // Verification fails. |
| 505 EXPECT_FALSE(verified); | 482 EXPECT_EQ(DownloadTargetResult::PATH_NOT_WRITEABLE, result); |
| 506 #if BUILDFLAG(ANDROID_JAVA_UI) | 483 #if BUILDFLAG(ANDROID_JAVA_UI) |
| 507 EXPECT_TRUE(reserved_path.empty()); | 484 EXPECT_TRUE(reserved_path.empty()); |
| 508 #else | 485 #else |
| 509 EXPECT_EQ(path.BaseName().value(), reserved_path.BaseName().value()); | 486 EXPECT_EQ(path.BaseName().value(), reserved_path.BaseName().value()); |
| 510 #endif | 487 #endif |
| 511 } | 488 } |
| 512 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); | 489 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); |
| 513 } | 490 } |
| 514 | 491 |
| 515 // If the default download directory doesn't exist, then it should be | 492 // If the default download directory doesn't exist, then it should be |
| 516 // created. But only if we are actually going to create the download path there. | 493 // created. But only if we are actually going to create the download path there. |
| 517 TEST_F(DownloadPathReservationTrackerTest, CreateDefaultDownloadPath) { | 494 TEST_F(DownloadPathReservationTrackerTest, CreateDefaultDownloadPath) { |
| 518 base::FilePath path( | 495 base::FilePath path( |
| 519 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo/foo.txt"))); | 496 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo/foo.txt"))); |
| 520 base::FilePath dir(path.DirName()); | 497 base::FilePath dir(path.DirName()); |
| 521 ASSERT_FALSE(base::DirectoryExists(dir)); | 498 ASSERT_FALSE(base::DirectoryExists(dir)); |
| 522 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 499 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 523 DownloadPathReservationTracker::OVERWRITE; | 500 DownloadPathReservationTracker::OVERWRITE; |
| 524 bool create_directory = false; | 501 bool create_directory = false; |
| 525 | 502 |
| 526 { | 503 { |
| 527 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); | 504 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); |
| 528 base::FilePath reserved_path; | 505 base::FilePath reserved_path; |
| 529 bool verified = true; | 506 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 530 CallGetReservedPath( | 507 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 531 item.get(), | 508 &reserved_path, &result); |
| 532 path, | |
| 533 create_directory, | |
| 534 conflict_action, | |
| 535 &reserved_path, | |
| 536 &verified); | |
| 537 // Verification fails because the directory doesn't exist. | 509 // Verification fails because the directory doesn't exist. |
| 538 EXPECT_FALSE(verified); | 510 EXPECT_EQ(DownloadTargetResult::PATH_NOT_WRITEABLE, result); |
| 539 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); | 511 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); |
| 540 } | 512 } |
| 541 ASSERT_FALSE(IsPathInUse(path)); | 513 ASSERT_FALSE(IsPathInUse(path)); |
| 542 { | 514 { |
| 543 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); | 515 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); |
| 544 base::FilePath reserved_path; | 516 base::FilePath reserved_path; |
| 545 bool verified = true; | 517 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 546 set_default_download_path(dir); | 518 set_default_download_path(dir); |
| 547 CallGetReservedPath( | 519 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 548 item.get(), | 520 &reserved_path, &result); |
| 549 path, | |
| 550 create_directory, | |
| 551 conflict_action, | |
| 552 &reserved_path, | |
| 553 &verified); | |
| 554 // Verification succeeds because the directory is created. | 521 // Verification succeeds because the directory is created. |
| 555 EXPECT_TRUE(verified); | 522 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 556 EXPECT_TRUE(base::DirectoryExists(dir)); | 523 EXPECT_TRUE(base::DirectoryExists(dir)); |
| 557 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); | 524 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); |
| 558 } | 525 } |
| 559 } | 526 } |
| 560 | 527 |
| 561 // If the target path of the download item changes, the reservation should be | 528 // If the target path of the download item changes, the reservation should be |
| 562 // updated to match. | 529 // updated to match. |
| 563 TEST_F(DownloadPathReservationTrackerTest, UpdatesToTargetPath) { | 530 TEST_F(DownloadPathReservationTrackerTest, UpdatesToTargetPath) { |
| 564 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); | 531 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); |
| 565 base::FilePath path( | 532 base::FilePath path( |
| 566 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); | 533 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); |
| 567 ASSERT_FALSE(IsPathInUse(path)); | 534 ASSERT_FALSE(IsPathInUse(path)); |
| 568 | 535 |
| 569 base::FilePath reserved_path; | 536 base::FilePath reserved_path; |
| 570 bool verified = false; | 537 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 571 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 538 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 572 DownloadPathReservationTracker::OVERWRITE; | 539 DownloadPathReservationTracker::OVERWRITE; |
| 573 bool create_directory = false; | 540 bool create_directory = false; |
| 574 CallGetReservedPath( | 541 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 575 item.get(), | 542 &reserved_path, &result); |
| 576 path, | |
| 577 create_directory, | |
| 578 conflict_action, | |
| 579 &reserved_path, | |
| 580 &verified); | |
| 581 EXPECT_TRUE(IsPathInUse(path)); | 543 EXPECT_TRUE(IsPathInUse(path)); |
| 582 EXPECT_TRUE(verified); | 544 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 583 EXPECT_EQ(path.value(), reserved_path.value()); | 545 EXPECT_EQ(path.value(), reserved_path.value()); |
| 584 | 546 |
| 585 // The target path is initially empty. If an OnDownloadUpdated() is issued in | 547 // The target path is initially empty. If an OnDownloadUpdated() is issued in |
| 586 // this state, we shouldn't lose the reservation. | 548 // this state, we shouldn't lose the reservation. |
| 587 ASSERT_EQ(base::FilePath::StringType(), item->GetTargetFilePath().value()); | 549 ASSERT_EQ(base::FilePath::StringType(), item->GetTargetFilePath().value()); |
| 588 item->NotifyObserversDownloadUpdated(); | 550 item->NotifyObserversDownloadUpdated(); |
| 589 base::RunLoop().RunUntilIdle(); | 551 base::RunLoop().RunUntilIdle(); |
| 590 EXPECT_TRUE(IsPathInUse(path)); | 552 EXPECT_TRUE(IsPathInUse(path)); |
| 591 | 553 |
| 592 // If the target path changes, we should update the reservation to match. | 554 // If the target path changes, we should update the reservation to match. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 619 // TODO(kinaba): the current implementation leaves spaces for appending | 581 // TODO(kinaba): the current implementation leaves spaces for appending |
| 620 // ".crdownload". So take it into account. Should be removed in the future. | 582 // ".crdownload". So take it into account. Should be removed in the future. |
| 621 const size_t max_length = real_max_length - 11; | 583 const size_t max_length = real_max_length - 11; |
| 622 | 584 |
| 623 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); | 585 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); |
| 624 base::FilePath path(GetLongNamePathInDownloadsDirectory( | 586 base::FilePath path(GetLongNamePathInDownloadsDirectory( |
| 625 max_length, FILE_PATH_LITERAL(".txt"))); | 587 max_length, FILE_PATH_LITERAL(".txt"))); |
| 626 ASSERT_FALSE(IsPathInUse(path)); | 588 ASSERT_FALSE(IsPathInUse(path)); |
| 627 | 589 |
| 628 base::FilePath reserved_path; | 590 base::FilePath reserved_path; |
| 629 bool verified = false; | 591 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 630 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 592 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 631 DownloadPathReservationTracker::OVERWRITE; | 593 DownloadPathReservationTracker::OVERWRITE; |
| 632 bool create_directory = false; | 594 bool create_directory = false; |
| 633 CallGetReservedPath( | 595 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 634 item.get(), | 596 &reserved_path, &result); |
| 635 path, | |
| 636 create_directory, | |
| 637 conflict_action, | |
| 638 &reserved_path, | |
| 639 &verified); | |
| 640 EXPECT_TRUE(IsPathInUse(reserved_path)); | 597 EXPECT_TRUE(IsPathInUse(reserved_path)); |
| 641 EXPECT_TRUE(verified); | 598 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 642 // The file name length is truncated to max_length. | 599 // The file name length is truncated to max_length. |
| 643 EXPECT_EQ(max_length, reserved_path.BaseName().value().size()); | 600 EXPECT_EQ(max_length, reserved_path.BaseName().value().size()); |
| 644 // But the extension is kept unchanged. | 601 // But the extension is kept unchanged. |
| 645 EXPECT_EQ(path.Extension(), reserved_path.Extension()); | 602 EXPECT_EQ(path.Extension(), reserved_path.Extension()); |
| 646 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); | 603 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); |
| 647 } | 604 } |
| 648 | 605 |
| 649 TEST_F(DownloadPathReservationTrackerTest, TruncationConflict) { | 606 TEST_F(DownloadPathReservationTrackerTest, TruncationConflict) { |
| 650 int real_max_length = | 607 int real_max_length = |
| 651 base::GetMaximumPathComponentLength(default_download_path()); | 608 base::GetMaximumPathComponentLength(default_download_path()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 662 base::FilePath path2(GetLongNamePathInDownloadsDirectory( | 619 base::FilePath path2(GetLongNamePathInDownloadsDirectory( |
| 663 max_length - 8, FILE_PATH_LITERAL(" (2).txt"))); | 620 max_length - 8, FILE_PATH_LITERAL(" (2).txt"))); |
| 664 ASSERT_FALSE(IsPathInUse(path)); | 621 ASSERT_FALSE(IsPathInUse(path)); |
| 665 // "aaa...aaaaaaa.txt" (truncated path) and | 622 // "aaa...aaaaaaa.txt" (truncated path) and |
| 666 // "aaa...aaa (1).txt" (truncated and first uniquification try) exists. | 623 // "aaa...aaa (1).txt" (truncated and first uniquification try) exists. |
| 667 // "aaa...aaa (2).txt" should be used. | 624 // "aaa...aaa (2).txt" should be used. |
| 668 ASSERT_EQ(0, base::WriteFile(path0, "", 0)); | 625 ASSERT_EQ(0, base::WriteFile(path0, "", 0)); |
| 669 ASSERT_EQ(0, base::WriteFile(path1, "", 0)); | 626 ASSERT_EQ(0, base::WriteFile(path1, "", 0)); |
| 670 | 627 |
| 671 base::FilePath reserved_path; | 628 base::FilePath reserved_path; |
| 672 bool verified = false; | 629 DownloadTargetResult result = DownloadTargetResult::NAME_TOO_LONG; |
| 673 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 630 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 674 DownloadPathReservationTracker::UNIQUIFY; | 631 DownloadPathReservationTracker::UNIQUIFY; |
| 675 bool create_directory = false; | 632 bool create_directory = false; |
| 676 CallGetReservedPath( | 633 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 677 item.get(), | 634 &reserved_path, &result); |
| 678 path, | |
| 679 create_directory, | |
| 680 conflict_action, | |
| 681 &reserved_path, | |
| 682 &verified); | |
| 683 EXPECT_TRUE(IsPathInUse(reserved_path)); | 635 EXPECT_TRUE(IsPathInUse(reserved_path)); |
| 684 EXPECT_TRUE(verified); | 636 EXPECT_EQ(DownloadTargetResult::SUCCESS, result); |
| 685 EXPECT_EQ(path2, reserved_path); | 637 EXPECT_EQ(path2, reserved_path); |
| 686 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); | 638 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); |
| 687 } | 639 } |
| 688 | 640 |
| 689 TEST_F(DownloadPathReservationTrackerTest, TruncationFail) { | 641 TEST_F(DownloadPathReservationTrackerTest, TruncationFail) { |
| 690 int real_max_length = | 642 int real_max_length = |
| 691 base::GetMaximumPathComponentLength(default_download_path()); | 643 base::GetMaximumPathComponentLength(default_download_path()); |
| 692 ASSERT_NE(-1, real_max_length); | 644 ASSERT_NE(-1, real_max_length); |
| 693 const size_t max_length = real_max_length - 11; | 645 const size_t max_length = real_max_length - 11; |
| 694 | 646 |
| 695 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); | 647 std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1)); |
| 696 base::FilePath path(GetPathInDownloadsDirectory( | 648 base::FilePath path(GetPathInDownloadsDirectory( |
| 697 (FILE_PATH_LITERAL("a.") + | 649 (FILE_PATH_LITERAL("a.") + |
| 698 base::FilePath::StringType(max_length, 'b')).c_str())); | 650 base::FilePath::StringType(max_length, 'b')).c_str())); |
| 699 ASSERT_FALSE(IsPathInUse(path)); | 651 ASSERT_FALSE(IsPathInUse(path)); |
| 700 | 652 |
| 701 base::FilePath reserved_path; | 653 base::FilePath reserved_path; |
| 702 bool verified = false; | 654 DownloadTargetResult result = DownloadTargetResult::SUCCESS; |
| 703 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 655 DownloadPathReservationTracker::FilenameConflictAction conflict_action = |
| 704 DownloadPathReservationTracker::OVERWRITE; | 656 DownloadPathReservationTracker::OVERWRITE; |
| 705 bool create_directory = false; | 657 bool create_directory = false; |
| 706 CallGetReservedPath( | 658 CallGetReservedPath(item.get(), path, create_directory, conflict_action, |
| 707 item.get(), | 659 &reserved_path, &result); |
| 708 path, | |
| 709 create_directory, | |
| 710 conflict_action, | |
| 711 &reserved_path, | |
| 712 &verified); | |
| 713 // We cannot truncate a path with very long extension. | 660 // We cannot truncate a path with very long extension. |
| 714 EXPECT_FALSE(verified); | 661 EXPECT_EQ(DownloadTargetResult::NAME_TOO_LONG, result); |
| 715 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); | 662 SetDownloadItemState(item.get(), DownloadItem::COMPLETE); |
| 716 } | 663 } |
| 717 | 664 |
| 718 #endif // Platforms that support filename truncation. | 665 #endif // Platforms that support filename truncation. |
| OLD | NEW |