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.
5 #include "base/files/file_path.h"
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/observer_list.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/test/test_file_util.h"
13 #include "chrome/browser/download/download_path_reservation_tracker.h"
14 #include "chrome/browser/download/download_target_determiner.h"
15 #include "content/public/test/mock_download_item.h"
16 #include "content/public/test/test_browser_thread.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 using content::BrowserThread
;
21 using content::DownloadItem
;
22 using content::MockDownloadItem
;
23 using testing::AnyNumber
;
24 using testing::Return
;
25 using testing::ReturnRef
;
26 using testing::ReturnRefOfCopy
;
30 class DownloadPathReservationTrackerTest
: public testing::Test
{
32 DownloadPathReservationTrackerTest();
35 void SetUp() override
;
36 void TearDown() override
;
38 MockDownloadItem
* CreateDownloadItem(int32 id
);
39 base::FilePath
GetPathInDownloadsDirectory(
40 const base::FilePath::CharType
* suffix
);
41 bool IsPathInUse(const base::FilePath
& path
);
42 void CallGetReservedPath(
43 DownloadItem
* download_item
,
44 const base::FilePath
& target_path
,
45 bool create_directory
,
46 DownloadPathReservationTracker::FilenameConflictAction conflict_action
,
47 base::FilePath
* return_path
,
48 bool* return_verified
);
50 const base::FilePath
& default_download_path() const {
51 return default_download_path_
;
53 void set_default_download_path(const base::FilePath
& path
) {
54 default_download_path_
= path
;
56 // Creates a name of form 'a'*repeat + suffix
57 base::FilePath
GetLongNamePathInDownloadsDirectory(
58 size_t repeat
, const base::FilePath::CharType
* suffix
);
61 base::ScopedTempDir test_download_dir_
;
62 base::FilePath default_download_path_
;
63 base::MessageLoopForUI message_loop_
;
64 content::TestBrowserThread ui_thread_
;
65 content::TestBrowserThread file_thread_
;
68 void TestReservedPathCallback(base::FilePath
* return_path
,
69 bool* return_verified
, bool* did_run_callback
,
70 const base::FilePath
& path
, bool verified
);
73 DownloadPathReservationTrackerTest::DownloadPathReservationTrackerTest()
74 : ui_thread_(BrowserThread::UI
, &message_loop_
),
75 file_thread_(BrowserThread::FILE, &message_loop_
) {
78 void DownloadPathReservationTrackerTest::SetUp() {
79 ASSERT_TRUE(test_download_dir_
.CreateUniqueTempDir());
80 set_default_download_path(test_download_dir_
.path());
83 void DownloadPathReservationTrackerTest::TearDown() {
84 message_loop_
.RunUntilIdle();
87 MockDownloadItem
* DownloadPathReservationTrackerTest::CreateDownloadItem(
89 MockDownloadItem
* item
= new ::testing::StrictMock
<MockDownloadItem
>;
90 EXPECT_CALL(*item
, GetId())
91 .WillRepeatedly(Return(id
));
92 EXPECT_CALL(*item
, GetTargetFilePath())
93 .WillRepeatedly(ReturnRefOfCopy(base::FilePath()));
94 EXPECT_CALL(*item
, GetState())
95 .WillRepeatedly(Return(DownloadItem::IN_PROGRESS
));
99 base::FilePath
DownloadPathReservationTrackerTest::GetPathInDownloadsDirectory(
100 const base::FilePath::CharType
* suffix
) {
101 return default_download_path().Append(suffix
).NormalizePathSeparators();
104 bool DownloadPathReservationTrackerTest::IsPathInUse(
105 const base::FilePath
& path
) {
106 return DownloadPathReservationTracker::IsPathInUseForTesting(path
);
109 void DownloadPathReservationTrackerTest::CallGetReservedPath(
110 DownloadItem
* download_item
,
111 const base::FilePath
& target_path
,
112 bool create_directory
,
113 DownloadPathReservationTracker::FilenameConflictAction conflict_action
,
114 base::FilePath
* return_path
,
115 bool* return_verified
) {
116 // Weak pointer factory to prevent the callback from running after this
117 // function has returned.
118 base::WeakPtrFactory
<DownloadPathReservationTrackerTest
> weak_ptr_factory(
120 bool did_run_callback
= false;
121 DownloadPathReservationTracker::GetReservedPath(
124 default_download_path(),
127 base::Bind(&DownloadPathReservationTrackerTest::TestReservedPathCallback
,
128 weak_ptr_factory
.GetWeakPtr(), return_path
, return_verified
,
130 message_loop_
.RunUntilIdle();
131 EXPECT_TRUE(did_run_callback
);
134 void DownloadPathReservationTrackerTest::TestReservedPathCallback(
135 base::FilePath
* return_path
, bool* return_verified
, bool* did_run_callback
,
136 const base::FilePath
& path
, bool verified
) {
137 *did_run_callback
= true;
139 *return_verified
= verified
;
143 DownloadPathReservationTrackerTest::GetLongNamePathInDownloadsDirectory(
144 size_t repeat
, const base::FilePath::CharType
* suffix
) {
145 return GetPathInDownloadsDirectory(
146 (base::FilePath::StringType(repeat
, FILE_PATH_LITERAL('a'))
150 void SetDownloadItemState(content::MockDownloadItem
* download_item
,
151 content::DownloadItem::DownloadState state
) {
152 EXPECT_CALL(*download_item
, GetState())
153 .WillRepeatedly(Return(state
));
154 download_item
->NotifyObserversDownloadUpdated();
159 // A basic reservation is acquired and committed.
160 TEST_F(DownloadPathReservationTrackerTest
, BasicReservation
) {
161 scoped_ptr
<MockDownloadItem
> item(CreateDownloadItem(1));
163 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
164 ASSERT_FALSE(IsPathInUse(path
));
166 base::FilePath reserved_path
;
167 bool verified
= false;
168 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
169 DownloadPathReservationTracker::OVERWRITE
;
170 bool create_directory
= false;
178 EXPECT_TRUE(IsPathInUse(path
));
179 EXPECT_TRUE(verified
);
180 EXPECT_EQ(path
.value(), reserved_path
.value());
182 // Destroying the item should release the reservation.
183 SetDownloadItemState(item
.get(), DownloadItem::COMPLETE
);
185 message_loop_
.RunUntilIdle();
186 EXPECT_FALSE(IsPathInUse(path
));
189 // A download that is interrupted should lose its reservation.
190 TEST_F(DownloadPathReservationTrackerTest
, InterruptedDownload
) {
191 scoped_ptr
<MockDownloadItem
> item(CreateDownloadItem(1));
193 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
194 ASSERT_FALSE(IsPathInUse(path
));
196 base::FilePath reserved_path
;
197 bool verified
= false;
198 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
199 DownloadPathReservationTracker::OVERWRITE
;
200 bool create_directory
= false;
208 EXPECT_TRUE(IsPathInUse(path
));
209 EXPECT_TRUE(verified
);
210 EXPECT_EQ(path
.value(), reserved_path
.value());
212 // Once the download is interrupted, the path should become available again.
213 SetDownloadItemState(item
.get(), DownloadItem::INTERRUPTED
);
214 message_loop_
.RunUntilIdle();
215 EXPECT_FALSE(IsPathInUse(path
));
218 // A completed download should also lose its reservation.
219 TEST_F(DownloadPathReservationTrackerTest
, CompleteDownload
) {
220 scoped_ptr
<MockDownloadItem
> item(CreateDownloadItem(1));
222 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
223 ASSERT_FALSE(IsPathInUse(path
));
225 base::FilePath reserved_path
;
226 bool verified
= false;
227 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
228 DownloadPathReservationTracker::OVERWRITE
;
229 bool create_directory
= false;
237 EXPECT_TRUE(IsPathInUse(path
));
238 EXPECT_TRUE(verified
);
239 EXPECT_EQ(path
.value(), reserved_path
.value());
241 // Once the download completes, the path should become available again. For a
242 // real download, at this point only the path reservation will be released.
243 // The path wouldn't be available since it is occupied on disk by the
244 // completed download.
245 SetDownloadItemState(item
.get(), DownloadItem::COMPLETE
);
246 message_loop_
.RunUntilIdle();
247 EXPECT_FALSE(IsPathInUse(path
));
250 // If there are files on the file system, a unique reservation should uniquify
252 TEST_F(DownloadPathReservationTrackerTest
, ConflictingFiles
) {
253 scoped_ptr
<MockDownloadItem
> item(CreateDownloadItem(1));
255 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
256 base::FilePath
path1(
257 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")));
258 // Create a file at |path|, and a .crdownload file at |path1|.
259 ASSERT_EQ(0, base::WriteFile(path
, "", 0));
262 DownloadTargetDeterminer::GetCrDownloadPath(path1
), "", 0));
263 ASSERT_TRUE(IsPathInUse(path
));
265 base::FilePath reserved_path
;
266 bool verified
= false;
267 bool create_directory
= false;
268 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
269 DownloadPathReservationTracker::UNIQUIFY
;
277 EXPECT_TRUE(IsPathInUse(path
));
278 EXPECT_TRUE(IsPathInUse(reserved_path
));
279 EXPECT_TRUE(verified
);
280 // The path should be uniquified, skipping over foo.txt but not over
281 // "foo (1).txt.crdownload"
283 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")).value(),
284 reserved_path
.value());
286 SetDownloadItemState(item
.get(), DownloadItem::COMPLETE
);
288 message_loop_
.RunUntilIdle();
289 EXPECT_TRUE(IsPathInUse(path
));
290 EXPECT_FALSE(IsPathInUse(reserved_path
));
293 // Multiple reservations for the same path should uniquify around each other.
294 TEST_F(DownloadPathReservationTrackerTest
, ConflictingReservations
) {
295 scoped_ptr
<MockDownloadItem
> item1(CreateDownloadItem(1));
297 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
298 base::FilePath
uniquified_path(
299 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")));
300 ASSERT_FALSE(IsPathInUse(path
));
301 ASSERT_FALSE(IsPathInUse(uniquified_path
));
303 base::FilePath reserved_path1
;
304 bool verified
= false;
305 bool create_directory
= false;
307 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
308 DownloadPathReservationTracker::UNIQUIFY
;
316 EXPECT_TRUE(IsPathInUse(path
));
317 EXPECT_TRUE(verified
);
321 // Requesting a reservation for the same path with uniquification results in
322 // a uniquified path.
323 scoped_ptr
<MockDownloadItem
> item2(CreateDownloadItem(2));
324 base::FilePath reserved_path2
;
332 EXPECT_TRUE(IsPathInUse(path
));
333 EXPECT_TRUE(IsPathInUse(uniquified_path
));
334 EXPECT_EQ(uniquified_path
.value(), reserved_path2
.value());
335 SetDownloadItemState(item2
.get(), DownloadItem::COMPLETE
);
337 message_loop_
.RunUntilIdle();
338 EXPECT_TRUE(IsPathInUse(path
));
339 EXPECT_FALSE(IsPathInUse(uniquified_path
));
342 // Since the previous download item was removed, requesting a reservation
343 // for the same path should result in the same uniquified path.
344 scoped_ptr
<MockDownloadItem
> item2(CreateDownloadItem(2));
345 base::FilePath reserved_path2
;
353 EXPECT_TRUE(IsPathInUse(path
));
354 EXPECT_TRUE(IsPathInUse(uniquified_path
));
355 EXPECT_EQ(uniquified_path
.value(), reserved_path2
.value());
356 SetDownloadItemState(item2
.get(), DownloadItem::COMPLETE
);
358 message_loop_
.RunUntilIdle();
360 // Now acquire an overwriting reservation. We should end up with the same
361 // non-uniquified path for both reservations.
362 scoped_ptr
<MockDownloadItem
> item3(CreateDownloadItem(2));
363 base::FilePath reserved_path3
;
364 conflict_action
= DownloadPathReservationTracker::OVERWRITE
;
372 EXPECT_TRUE(IsPathInUse(path
));
373 EXPECT_FALSE(IsPathInUse(uniquified_path
));
375 EXPECT_EQ(path
.value(), reserved_path1
.value());
376 EXPECT_EQ(path
.value(), reserved_path3
.value());
378 SetDownloadItemState(item1
.get(), DownloadItem::COMPLETE
);
379 SetDownloadItemState(item3
.get(), DownloadItem::COMPLETE
);
382 // If a unique path cannot be determined after trying kMaxUniqueFiles
383 // uniquifiers, then the callback should notified that verification failed, and
384 // the returned path should be set to the original requested path.
385 TEST_F(DownloadPathReservationTrackerTest
, UnresolvedConflicts
) {
387 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
388 scoped_ptr
<MockDownloadItem
>
389 items
[DownloadPathReservationTracker::kMaxUniqueFiles
+ 1];
390 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
391 DownloadPathReservationTracker::UNIQUIFY
;
392 bool create_directory
= false;
394 // Create |kMaxUniqueFiles + 1| reservations for |path|. The first reservation
395 // will have no uniquifier. The |kMaxUniqueFiles| remaining reservations do.
396 for (int i
= 0; i
<= DownloadPathReservationTracker::kMaxUniqueFiles
; i
++) {
397 base::FilePath reserved_path
;
398 base::FilePath expected_path
;
399 bool verified
= false;
402 path
.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", i
));
404 expected_path
= path
;
406 items
[i
].reset(CreateDownloadItem(i
));
407 EXPECT_FALSE(IsPathInUse(expected_path
));
415 EXPECT_TRUE(IsPathInUse(expected_path
));
416 EXPECT_EQ(expected_path
.value(), reserved_path
.value());
417 EXPECT_TRUE(verified
);
419 // The next reservation for |path| will fail to be unique.
420 scoped_ptr
<MockDownloadItem
> item(
421 CreateDownloadItem(DownloadPathReservationTracker::kMaxUniqueFiles
+ 1));
422 base::FilePath reserved_path
;
423 bool verified
= true;
431 EXPECT_FALSE(verified
);
432 EXPECT_EQ(path
.value(), reserved_path
.value());
434 SetDownloadItemState(item
.get(), DownloadItem::COMPLETE
);
435 for (int i
= 0; i
<= DownloadPathReservationTracker::kMaxUniqueFiles
; i
++)
436 SetDownloadItemState(items
[i
].get(), DownloadItem::COMPLETE
);
439 // If the target directory is unwriteable, then callback should be notified that
440 // verification failed.
441 TEST_F(DownloadPathReservationTrackerTest
, UnwriteableDirectory
) {
442 scoped_ptr
<MockDownloadItem
> item(CreateDownloadItem(1));
444 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
445 base::FilePath
dir(path
.DirName());
446 ASSERT_FALSE(IsPathInUse(path
));
449 // Scope for FilePermissionRestorer
450 base::FilePermissionRestorer
restorer(dir
);
451 EXPECT_TRUE(base::MakeFileUnwritable(dir
));
452 base::FilePath reserved_path
;
453 bool verified
= true;
454 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
455 DownloadPathReservationTracker::OVERWRITE
;
456 bool create_directory
= false;
464 // Verification fails.
465 EXPECT_FALSE(verified
);
466 EXPECT_EQ(path
.BaseName().value(), reserved_path
.BaseName().value());
468 SetDownloadItemState(item
.get(), DownloadItem::COMPLETE
);
471 // If the default download directory doesn't exist, then it should be
472 // created. But only if we are actually going to create the download path there.
473 TEST_F(DownloadPathReservationTrackerTest
, CreateDefaultDownloadPath
) {
475 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo/foo.txt")));
476 base::FilePath
dir(path
.DirName());
477 ASSERT_FALSE(base::DirectoryExists(dir
));
478 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
479 DownloadPathReservationTracker::OVERWRITE
;
480 bool create_directory
= false;
483 scoped_ptr
<MockDownloadItem
> item(CreateDownloadItem(1));
484 base::FilePath reserved_path
;
485 bool verified
= true;
493 // Verification fails because the directory doesn't exist.
494 EXPECT_FALSE(verified
);
495 SetDownloadItemState(item
.get(), DownloadItem::COMPLETE
);
497 ASSERT_FALSE(IsPathInUse(path
));
499 scoped_ptr
<MockDownloadItem
> item(CreateDownloadItem(1));
500 base::FilePath reserved_path
;
501 bool verified
= true;
502 set_default_download_path(dir
);
510 // Verification succeeds because the directory is created.
511 EXPECT_TRUE(verified
);
512 EXPECT_TRUE(base::DirectoryExists(dir
));
513 SetDownloadItemState(item
.get(), DownloadItem::COMPLETE
);
517 // If the target path of the download item changes, the reservation should be
519 TEST_F(DownloadPathReservationTrackerTest
, UpdatesToTargetPath
) {
520 scoped_ptr
<MockDownloadItem
> item(CreateDownloadItem(1));
522 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
523 ASSERT_FALSE(IsPathInUse(path
));
525 base::FilePath reserved_path
;
526 bool verified
= false;
527 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
528 DownloadPathReservationTracker::OVERWRITE
;
529 bool create_directory
= false;
537 EXPECT_TRUE(IsPathInUse(path
));
538 EXPECT_TRUE(verified
);
539 EXPECT_EQ(path
.value(), reserved_path
.value());
541 // The target path is initially empty. If an OnDownloadUpdated() is issued in
542 // this state, we shouldn't lose the reservation.
543 ASSERT_EQ(base::FilePath::StringType(), item
->GetTargetFilePath().value());
544 item
->NotifyObserversDownloadUpdated();
545 message_loop_
.RunUntilIdle();
546 EXPECT_TRUE(IsPathInUse(path
));
548 // If the target path changes, we should update the reservation to match.
549 base::FilePath
new_target_path(
550 GetPathInDownloadsDirectory(FILE_PATH_LITERAL("bar.txt")));
551 ASSERT_FALSE(IsPathInUse(new_target_path
));
552 EXPECT_CALL(*item
, GetTargetFilePath())
553 .WillRepeatedly(ReturnRef(new_target_path
));
554 item
->NotifyObserversDownloadUpdated();
555 message_loop_
.RunUntilIdle();
556 EXPECT_FALSE(IsPathInUse(path
));
557 EXPECT_TRUE(IsPathInUse(new_target_path
));
559 // Destroying the item should release the reservation.
560 SetDownloadItemState(item
.get(), DownloadItem::COMPLETE
);
562 message_loop_
.RunUntilIdle();
563 EXPECT_FALSE(IsPathInUse(new_target_path
));
566 // Tests for long name truncation. On other platforms automatic truncation
567 // is not performed (yet).
568 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
570 TEST_F(DownloadPathReservationTrackerTest
, BasicTruncation
) {
571 int real_max_length
=
572 base::GetMaximumPathComponentLength(default_download_path());
573 ASSERT_NE(-1, real_max_length
);
575 // TODO(kinaba): the current implementation leaves spaces for appending
576 // ".crdownload". So take it into account. Should be removed in the future.
577 const size_t max_length
= real_max_length
- 11;
579 scoped_ptr
<MockDownloadItem
> item(CreateDownloadItem(1));
580 base::FilePath
path(GetLongNamePathInDownloadsDirectory(
581 max_length
, FILE_PATH_LITERAL(".txt")));
582 ASSERT_FALSE(IsPathInUse(path
));
584 base::FilePath reserved_path
;
585 bool verified
= false;
586 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
587 DownloadPathReservationTracker::OVERWRITE
;
588 bool create_directory
= false;
596 EXPECT_TRUE(IsPathInUse(reserved_path
));
597 EXPECT_TRUE(verified
);
598 // The file name length is truncated to max_length.
599 EXPECT_EQ(max_length
, reserved_path
.BaseName().value().size());
600 // But the extension is kept unchanged.
601 EXPECT_EQ(path
.Extension(), reserved_path
.Extension());
602 SetDownloadItemState(item
.get(), DownloadItem::COMPLETE
);
605 TEST_F(DownloadPathReservationTrackerTest
, TruncationConflict
) {
606 int real_max_length
=
607 base::GetMaximumPathComponentLength(default_download_path());
608 ASSERT_NE(-1, real_max_length
);
609 const size_t max_length
= real_max_length
- 11;
611 scoped_ptr
<MockDownloadItem
> item(CreateDownloadItem(1));
612 base::FilePath
path(GetLongNamePathInDownloadsDirectory(
613 max_length
, FILE_PATH_LITERAL(".txt")));
614 base::FilePath
path0(GetLongNamePathInDownloadsDirectory(
615 max_length
- 4, FILE_PATH_LITERAL(".txt")));
616 base::FilePath
path1(GetLongNamePathInDownloadsDirectory(
617 max_length
- 8, FILE_PATH_LITERAL(" (1).txt")));
618 base::FilePath
path2(GetLongNamePathInDownloadsDirectory(
619 max_length
- 8, FILE_PATH_LITERAL(" (2).txt")));
620 ASSERT_FALSE(IsPathInUse(path
));
621 // "aaa...aaaaaaa.txt" (truncated path) and
622 // "aaa...aaa (1).txt" (truncated and first uniquification try) exists.
623 // "aaa...aaa (2).txt" should be used.
624 ASSERT_EQ(0, base::WriteFile(path0
, "", 0));
625 ASSERT_EQ(0, base::WriteFile(path1
, "", 0));
627 base::FilePath reserved_path
;
628 bool verified
= false;
629 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
630 DownloadPathReservationTracker::UNIQUIFY
;
631 bool create_directory
= false;
639 EXPECT_TRUE(IsPathInUse(reserved_path
));
640 EXPECT_TRUE(verified
);
641 EXPECT_EQ(path2
, reserved_path
);
642 SetDownloadItemState(item
.get(), DownloadItem::COMPLETE
);
645 TEST_F(DownloadPathReservationTrackerTest
, TruncationFail
) {
646 int real_max_length
=
647 base::GetMaximumPathComponentLength(default_download_path());
648 ASSERT_NE(-1, real_max_length
);
649 const size_t max_length
= real_max_length
- 11;
651 scoped_ptr
<MockDownloadItem
> item(CreateDownloadItem(1));
652 base::FilePath
path(GetPathInDownloadsDirectory(
653 (FILE_PATH_LITERAL("a.") +
654 base::FilePath::StringType(max_length
, 'b')).c_str()));
655 ASSERT_FALSE(IsPathInUse(path
));
657 base::FilePath reserved_path
;
658 bool verified
= false;
659 DownloadPathReservationTracker::FilenameConflictAction conflict_action
=
660 DownloadPathReservationTracker::OVERWRITE
;
661 bool create_directory
= false;
669 // We cannot truncate a path with very long extension.
670 EXPECT_FALSE(verified
);
671 SetDownloadItemState(item
.get(), DownloadItem::COMPLETE
);