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.
7 #include "base/memory/weak_ptr.h"
8 #include "base/rand_util.h"
9 #include "base/stl_util.h"
10 #include "chrome/browser/download/download_history.h"
11 #include "chrome/browser/history/download_database.h"
12 #include "chrome/browser/history/download_row.h"
13 #include "chrome/browser/history/history_service.h"
14 #include "content/public/test/mock_download_item.h"
15 #include "content/public/test/mock_download_manager.h"
16 #include "content/public/test/test_browser_thread.h"
17 #include "content/public/test/test_utils.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 #if defined(ENABLE_EXTENSIONS)
21 #include "chrome/browser/extensions/api/downloads/downloads_api.h"
25 using testing::Invoke
;
26 using testing::Return
;
27 using testing::ReturnRefOfCopy
;
28 using testing::SetArgPointee
;
29 using testing::WithArg
;
34 void CheckInfoEqual(const history::DownloadRow
& left
,
35 const history::DownloadRow
& right
) {
36 EXPECT_EQ(left
.current_path
.value(), right
.current_path
.value());
37 EXPECT_EQ(left
.target_path
.value(), right
.target_path
.value());
38 EXPECT_EQ(left
.url_chain
.size(), right
.url_chain
.size());
39 for (unsigned int i
= 0;
40 i
< left
.url_chain
.size() && i
< right
.url_chain
.size();
42 EXPECT_EQ(left
.url_chain
[i
].spec(), right
.url_chain
[i
].spec());
44 EXPECT_EQ(left
.referrer_url
.spec(), right
.referrer_url
.spec());
45 EXPECT_EQ(left
.mime_type
, right
.mime_type
);
46 EXPECT_EQ(left
.original_mime_type
, right
.original_mime_type
);
47 EXPECT_EQ(left
.start_time
.ToTimeT(), right
.start_time
.ToTimeT());
48 EXPECT_EQ(left
.end_time
.ToTimeT(), right
.end_time
.ToTimeT());
49 EXPECT_EQ(left
.etag
, right
.etag
);
50 EXPECT_EQ(left
.last_modified
, right
.last_modified
);
51 EXPECT_EQ(left
.received_bytes
, right
.received_bytes
);
52 EXPECT_EQ(left
.total_bytes
, right
.total_bytes
);
53 EXPECT_EQ(left
.state
, right
.state
);
54 EXPECT_EQ(left
.danger_type
, right
.danger_type
);
55 EXPECT_EQ(left
.id
, right
.id
);
56 EXPECT_EQ(left
.opened
, right
.opened
);
57 EXPECT_EQ(left
.by_ext_id
, right
.by_ext_id
);
58 EXPECT_EQ(left
.by_ext_name
, right
.by_ext_name
);
61 typedef DownloadHistory::IdSet IdSet
;
62 typedef std::vector
<history::DownloadRow
> InfoVector
;
63 typedef testing::StrictMock
<content::MockDownloadItem
> StrictMockDownloadItem
;
65 class FakeHistoryAdapter
: public DownloadHistory::HistoryAdapter
{
68 : DownloadHistory::HistoryAdapter(NULL
),
69 slow_create_download_(false),
70 fail_create_download_(false) {
73 virtual ~FakeHistoryAdapter() {}
75 virtual void QueryDownloads(
76 const HistoryService::DownloadQueryCallback
& callback
) OVERRIDE
{
77 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
78 content::BrowserThread::PostTask(content::BrowserThread::UI
, FROM_HERE
,
79 base::Bind(&FakeHistoryAdapter::QueryDownloadsDone
,
80 base::Unretained(this), callback
));
83 void QueryDownloadsDone(
84 const HistoryService::DownloadQueryCallback
& callback
) {
85 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
86 CHECK(expect_query_downloads_
.get());
87 callback
.Run(expect_query_downloads_
.Pass());
90 void set_slow_create_download(bool slow
) { slow_create_download_
= slow
; }
92 virtual void CreateDownload(
93 const history::DownloadRow
& info
,
94 const HistoryService::DownloadCreateCallback
& callback
) OVERRIDE
{
95 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
96 create_download_info_
= info
;
97 // Must not call CreateDownload() again before FinishCreateDownload()!
98 DCHECK(create_download_callback_
.is_null());
99 create_download_callback_
= base::Bind(callback
, !fail_create_download_
);
100 fail_create_download_
= false;
101 if (!slow_create_download_
)
102 FinishCreateDownload();
105 void FinishCreateDownload() {
106 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
107 create_download_callback_
.Run();
108 create_download_callback_
.Reset();
111 virtual void UpdateDownload(
112 const history::DownloadRow
& info
) OVERRIDE
{
113 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
114 update_download_
= info
;
117 virtual void RemoveDownloads(const IdSet
& ids
) OVERRIDE
{
118 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
119 for (IdSet::const_iterator it
= ids
.begin();
120 it
!= ids
.end(); ++it
) {
121 remove_downloads_
.insert(*it
);
125 void ExpectWillQueryDownloads(scoped_ptr
<InfoVector
> infos
) {
126 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
127 expect_query_downloads_
= infos
.Pass();
130 void ExpectQueryDownloadsDone() {
131 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
132 EXPECT_TRUE(NULL
== expect_query_downloads_
.get());
135 void FailCreateDownload() {
136 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
137 fail_create_download_
= true;
140 void ExpectDownloadCreated(
141 const history::DownloadRow
& info
) {
142 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
143 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
144 CheckInfoEqual(info
, create_download_info_
);
145 create_download_info_
= history::DownloadRow();
148 void ExpectNoDownloadCreated() {
149 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
150 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
151 CheckInfoEqual(history::DownloadRow(), create_download_info_
);
154 void ExpectDownloadUpdated(const history::DownloadRow
& info
) {
155 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
156 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
157 CheckInfoEqual(update_download_
, info
);
158 update_download_
= history::DownloadRow();
161 void ExpectNoDownloadUpdated() {
162 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
163 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
164 CheckInfoEqual(history::DownloadRow(), update_download_
);
167 void ExpectNoDownloadsRemoved() {
168 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
169 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
170 EXPECT_EQ(0, static_cast<int>(remove_downloads_
.size()));
173 void ExpectDownloadsRemoved(const IdSet
& ids
) {
174 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
175 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
176 IdSet differences
= base::STLSetDifference
<IdSet
>(ids
, remove_downloads_
);
177 for (IdSet::const_iterator different
= differences
.begin();
178 different
!= differences
.end(); ++different
) {
179 EXPECT_TRUE(false) << *different
;
181 remove_downloads_
.clear();
185 bool slow_create_download_
;
186 bool fail_create_download_
;
187 base::Closure create_download_callback_
;
188 history::DownloadRow update_download_
;
189 scoped_ptr
<InfoVector
> expect_query_downloads_
;
190 IdSet remove_downloads_
;
191 history::DownloadRow create_download_info_
;
193 DISALLOW_COPY_AND_ASSIGN(FakeHistoryAdapter
);
196 class DownloadHistoryTest
: public testing::Test
{
198 // Generic callback that receives a pointer to a StrictMockDownloadItem.
199 typedef base::Callback
<void(content::MockDownloadItem
*)> DownloadItemCallback
;
201 DownloadHistoryTest()
202 : ui_thread_(content::BrowserThread::UI
, &loop_
),
203 manager_(new content::MockDownloadManager()),
205 manager_observer_(NULL
),
206 download_created_index_(0) {}
207 virtual ~DownloadHistoryTest() {
208 STLDeleteElements(&items_
);
212 virtual void TearDown() OVERRIDE
{
213 download_history_
.reset();
216 content::MockDownloadManager
& manager() { return *manager_
.get(); }
217 content::MockDownloadItem
& item(size_t index
) { return *items_
[index
]; }
218 DownloadHistory
* download_history() { return download_history_
.get(); }
220 void SetManagerObserver(
221 content::DownloadManager::Observer
* manager_observer
) {
222 manager_observer_
= manager_observer
;
224 content::DownloadManager::Observer
* manager_observer() {
225 return manager_observer_
;
228 void CreateDownloadHistory(scoped_ptr
<InfoVector
> infos
) {
229 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
231 EXPECT_CALL(manager(), AddObserver(_
)).WillOnce(WithArg
<0>(Invoke(
232 this, &DownloadHistoryTest::SetManagerObserver
)));
233 EXPECT_CALL(manager(), RemoveObserver(_
));
234 download_created_index_
= 0;
235 for (size_t index
= 0; index
< infos
->size(); ++index
) {
236 content::MockDownloadManager::CreateDownloadItemAdapter
adapter(
238 infos
->at(index
).current_path
,
239 infos
->at(index
).target_path
,
240 infos
->at(index
).url_chain
,
241 infos
->at(index
).referrer_url
,
242 infos
->at(index
).mime_type
,
243 infos
->at(index
).original_mime_type
,
244 infos
->at(index
).start_time
,
245 infos
->at(index
).end_time
,
246 infos
->at(index
).etag
,
247 infos
->at(index
).last_modified
,
248 infos
->at(index
).received_bytes
,
249 infos
->at(index
).total_bytes
,
250 infos
->at(index
).state
,
251 infos
->at(index
).danger_type
,
252 infos
->at(index
).interrupt_reason
,
253 infos
->at(index
).opened
);
254 EXPECT_CALL(manager(), MockCreateDownloadItem(adapter
))
257 this, &DownloadHistoryTest::CallOnDownloadCreatedInOrder
),
258 Return(&item(index
))));
260 EXPECT_CALL(manager(), CheckForHistoryFilesRemoval());
261 history_
= new FakeHistoryAdapter();
262 history_
->ExpectWillQueryDownloads(infos
.Pass());
263 EXPECT_CALL(*manager_
.get(), GetAllDownloads(_
)).WillRepeatedly(Return());
264 download_history_
.reset(new DownloadHistory(
265 &manager(), scoped_ptr
<DownloadHistory::HistoryAdapter
>(history_
)));
266 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
267 history_
->ExpectQueryDownloadsDone();
270 void CallOnDownloadCreated(size_t index
) {
271 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
272 if (!pre_on_create_handler_
.is_null())
273 pre_on_create_handler_
.Run(&item(index
));
274 manager_observer()->OnDownloadCreated(&manager(), &item(index
));
275 if (!post_on_create_handler_
.is_null())
276 post_on_create_handler_
.Run(&item(index
));
279 void CallOnDownloadCreatedInOrder() {
280 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
281 // Gmock doesn't appear to support something like InvokeWithTheseArgs. Maybe
282 // gmock needs to learn about base::Callback.
283 CallOnDownloadCreated(download_created_index_
++);
286 void set_slow_create_download(bool slow
) {
287 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
288 history_
->set_slow_create_download(slow
);
291 void FinishCreateDownload() {
292 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
293 history_
->FinishCreateDownload();
296 void FailCreateDownload() {
297 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
298 history_
->FailCreateDownload();
301 void ExpectDownloadCreated(
302 const history::DownloadRow
& info
) {
303 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
304 history_
->ExpectDownloadCreated(info
);
307 void ExpectNoDownloadCreated() {
308 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
309 history_
->ExpectNoDownloadCreated();
312 void ExpectDownloadUpdated(const history::DownloadRow
& info
) {
313 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
314 history_
->ExpectDownloadUpdated(info
);
317 void ExpectNoDownloadUpdated() {
318 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
319 history_
->ExpectNoDownloadUpdated();
322 void ExpectNoDownloadsRemoved() {
323 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
324 history_
->ExpectNoDownloadsRemoved();
327 void ExpectDownloadsRemoved(const IdSet
& ids
) {
328 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
329 history_
->ExpectDownloadsRemoved(ids
);
332 void ExpectDownloadsRestoredFromHistory(bool expected_value
) {
333 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
334 pre_on_create_handler_
=
335 base::Bind(&DownloadHistoryTest::CheckDownloadWasRestoredFromHistory
,
336 base::Unretained(this),
338 post_on_create_handler_
=
339 base::Bind(&DownloadHistoryTest::CheckDownloadWasRestoredFromHistory
,
340 base::Unretained(this),
344 void InitBasicItem(const base::FilePath::CharType
* path
,
345 const char* url_string
,
346 const char* referrer_string
,
347 history::DownloadRow
* info
) {
348 GURL
url(url_string
);
349 GURL
referrer(referrer_string
);
350 std::vector
<GURL
> url_chain
;
351 url_chain
.push_back(url
);
352 InitItem(static_cast<uint32
>(items_
.size() + 1),
353 base::FilePath(path
),
354 base::FilePath(path
),
357 "application/octet-stream",
358 "application/octet-stream",
359 (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
360 (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
365 content::DownloadItem::COMPLETE
,
366 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
,
367 content::DOWNLOAD_INTERRUPT_REASON_NONE
,
376 const base::FilePath
& current_path
,
377 const base::FilePath
& target_path
,
378 const std::vector
<GURL
>& url_chain
,
379 const GURL
& referrer
,
380 const std::string
& mime_type
,
381 const std::string
& original_mime_type
,
382 const base::Time
& start_time
,
383 const base::Time
& end_time
,
384 const std::string
& etag
,
385 const std::string
& last_modified
,
386 int64 received_bytes
,
388 content::DownloadItem::DownloadState state
,
389 content::DownloadDangerType danger_type
,
390 content::DownloadInterruptReason interrupt_reason
,
392 const std::string
& by_extension_id
,
393 const std::string
& by_extension_name
,
394 history::DownloadRow
* info
) {
395 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
397 size_t index
= items_
.size();
398 StrictMockDownloadItem
* mock_item
= new StrictMockDownloadItem();
399 items_
.push_back(mock_item
);
401 info
->current_path
= current_path
;
402 info
->target_path
= target_path
;
403 info
->url_chain
= url_chain
;
404 info
->referrer_url
= referrer
;
405 info
->mime_type
= mime_type
;
406 info
->original_mime_type
= original_mime_type
;
407 info
->start_time
= start_time
;
408 info
->end_time
= end_time
;
410 info
->last_modified
= last_modified
;
411 info
->received_bytes
= received_bytes
;
412 info
->total_bytes
= total_bytes
;
414 info
->danger_type
= danger_type
;
415 info
->interrupt_reason
= interrupt_reason
;
417 info
->opened
= opened
;
418 info
->by_ext_id
= by_extension_id
;
419 info
->by_ext_name
= by_extension_name
;
421 EXPECT_CALL(item(index
), GetId()).WillRepeatedly(Return(id
));
422 EXPECT_CALL(item(index
), GetFullPath())
423 .WillRepeatedly(ReturnRefOfCopy(current_path
));
424 EXPECT_CALL(item(index
), GetTargetFilePath())
425 .WillRepeatedly(ReturnRefOfCopy(target_path
));
426 DCHECK_LE(1u, url_chain
.size());
427 EXPECT_CALL(item(index
), GetURL())
428 .WillRepeatedly(ReturnRefOfCopy(url_chain
[0]));
429 EXPECT_CALL(item(index
), GetUrlChain())
430 .WillRepeatedly(ReturnRefOfCopy(url_chain
));
431 EXPECT_CALL(item(index
), GetMimeType()).WillRepeatedly(Return(mime_type
));
432 EXPECT_CALL(item(index
), GetOriginalMimeType()).WillRepeatedly(Return(
433 original_mime_type
));
434 EXPECT_CALL(item(index
), GetReferrerUrl())
435 .WillRepeatedly(ReturnRefOfCopy(referrer
));
436 EXPECT_CALL(item(index
), GetStartTime()).WillRepeatedly(Return(start_time
));
437 EXPECT_CALL(item(index
), GetEndTime()).WillRepeatedly(Return(end_time
));
438 EXPECT_CALL(item(index
), GetETag()).WillRepeatedly(ReturnRefOfCopy(etag
));
439 EXPECT_CALL(item(index
), GetLastModifiedTime())
440 .WillRepeatedly(ReturnRefOfCopy(last_modified
));
441 EXPECT_CALL(item(index
), GetReceivedBytes())
442 .WillRepeatedly(Return(received_bytes
));
443 EXPECT_CALL(item(index
), GetTotalBytes())
444 .WillRepeatedly(Return(total_bytes
));
445 EXPECT_CALL(item(index
), GetState()).WillRepeatedly(Return(state
));
446 EXPECT_CALL(item(index
), GetDangerType())
447 .WillRepeatedly(Return(danger_type
));
448 EXPECT_CALL(item(index
), GetLastReason())
449 .WillRepeatedly(Return(interrupt_reason
));
450 EXPECT_CALL(item(index
), GetOpened()).WillRepeatedly(Return(opened
));
451 EXPECT_CALL(item(index
), GetTargetDisposition())
453 Return(content::DownloadItem::TARGET_DISPOSITION_OVERWRITE
));
454 EXPECT_CALL(manager(), GetDownload(id
))
455 .WillRepeatedly(Return(&item(index
)));
456 EXPECT_CALL(item(index
), IsTemporary()).WillRepeatedly(Return(false));
457 #if defined(ENABLE_EXTENSIONS)
458 new extensions::DownloadedByExtension(
459 &item(index
), by_extension_id
, by_extension_name
);
462 std::vector
<content::DownloadItem
*> items
;
463 for (size_t i
= 0; i
< items_
.size(); ++i
) {
464 items
.push_back(&item(i
));
466 EXPECT_CALL(*manager_
.get(), GetAllDownloads(_
))
467 .WillRepeatedly(SetArgPointee
<0>(items
));
471 void CheckDownloadWasRestoredFromHistory(bool expected_value
,
472 content::MockDownloadItem
* item
) {
473 ASSERT_TRUE(download_history_
.get());
474 EXPECT_EQ(expected_value
, download_history_
->WasRestoredFromHistory(item
));
477 base::MessageLoopForUI loop_
;
478 content::TestBrowserThread ui_thread_
;
479 std::vector
<StrictMockDownloadItem
*> items_
;
480 scoped_ptr
<content::MockDownloadManager
> manager_
;
481 FakeHistoryAdapter
* history_
;
482 scoped_ptr
<DownloadHistory
> download_history_
;
483 content::DownloadManager::Observer
* manager_observer_
;
484 size_t download_created_index_
;
485 DownloadItemCallback pre_on_create_handler_
;
486 DownloadItemCallback post_on_create_handler_
;
488 DISALLOW_COPY_AND_ASSIGN(DownloadHistoryTest
);
491 // Test loading an item from the database, changing it, saving it back, removing
493 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_Load
) {
494 // Load a download from history, create the item, OnDownloadCreated,
495 // OnDownloadUpdated, OnDownloadRemoved.
496 history::DownloadRow info
;
497 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
498 "http://example.com/bar.pdf",
499 "http://example.com/referrer.html",
502 scoped_ptr
<InfoVector
> infos(new InfoVector());
503 infos
->push_back(info
);
504 CreateDownloadHistory(infos
.Pass());
505 ExpectNoDownloadCreated();
507 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
509 // Pretend that something changed on the item.
510 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
511 item(0).NotifyObserversDownloadUpdated();
513 ExpectDownloadUpdated(info
);
515 // Pretend that the user removed the item.
518 item(0).NotifyObserversDownloadRemoved();
519 ExpectDownloadsRemoved(ids
);
522 // Test that WasRestoredFromHistory accurately identifies downloads that were
523 // created from history, even during an OnDownloadCreated() handler.
524 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_WasRestoredFromHistory_True
) {
525 // This sets DownloadHistoryTest to call DH::WasRestoredFromHistory() both
526 // before and after DH::OnDownloadCreated() is called. At each call, the
527 // expected return value is |true| since the download was restored from
529 ExpectDownloadsRestoredFromHistory(true);
531 // Construct a DownloadHistory with a single history download. This results in
532 // DownloadManager::CreateDownload() being called for the restored download.
533 // The above test expectation should verify that the value of
534 // WasRestoredFromHistory is correct for this download.
535 history::DownloadRow info
;
536 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
537 "http://example.com/bar.pdf",
538 "http://example.com/referrer.html",
540 scoped_ptr
<InfoVector
> infos(new InfoVector());
541 infos
->push_back(info
);
542 CreateDownloadHistory(infos
.Pass());
544 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
547 // Test that WasRestoredFromHistory accurately identifies downloads that were
548 // not created from history.
549 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_WasRestoredFromHistory_False
) {
550 // This sets DownloadHistoryTest to call DH::WasRestoredFromHistory() both
551 // before and after DH::OnDownloadCreated() is called. At each call, the
552 // expected return value is |true| since the download was restored from
554 ExpectDownloadsRestoredFromHistory(false);
556 // Create a DownloadHistory with no history downloads. No
557 // DownloadManager::CreateDownload() calls are expected.
558 CreateDownloadHistory(scoped_ptr
<InfoVector
>(new InfoVector()));
560 // Notify DownloadHistory that a new download was created. The above test
561 // expecation should verify that WasRestoredFromHistory is correct for this
563 history::DownloadRow info
;
564 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
565 "http://example.com/bar.pdf",
566 "http://example.com/referrer.html",
568 CallOnDownloadCreated(0);
569 ExpectDownloadCreated(info
);
572 // Test creating an item, saving it to the database, changing it, saving it
573 // back, removing it.
574 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_Create
) {
575 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
576 // OnDownloadRemoved.
577 CreateDownloadHistory(scoped_ptr
<InfoVector
>(new InfoVector()));
579 history::DownloadRow info
;
580 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
581 "http://example.com/bar.pdf",
582 "http://example.com/referrer.html",
585 // Pretend the manager just created |item|.
586 CallOnDownloadCreated(0);
587 ExpectDownloadCreated(info
);
588 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
590 // Pretend that something changed on the item.
591 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
592 item(0).NotifyObserversDownloadUpdated();
594 ExpectDownloadUpdated(info
);
596 // Pretend that the user removed the item.
599 item(0).NotifyObserversDownloadRemoved();
600 ExpectDownloadsRemoved(ids
);
603 // Test that changes to persisted fields in a DownloadItem triggers database
605 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_Update
) {
606 CreateDownloadHistory(scoped_ptr
<InfoVector
>(new InfoVector()));
608 history::DownloadRow info
;
609 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
610 "http://example.com/bar.pdf",
611 "http://example.com/referrer.html",
613 CallOnDownloadCreated(0);
614 ExpectDownloadCreated(info
);
615 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
617 base::FilePath
new_path(FILE_PATH_LITERAL("/foo/baz.txt"));
618 base::Time
new_time(base::Time::Now());
619 std::string
new_etag("new etag");
620 std::string
new_last_modifed("new last modified");
623 EXPECT_CALL(item(0), GetFullPath()).WillRepeatedly(ReturnRefOfCopy(new_path
));
624 info
.current_path
= new_path
;
625 item(0).NotifyObserversDownloadUpdated();
626 ExpectDownloadUpdated(info
);
629 EXPECT_CALL(item(0), GetTargetFilePath())
630 .WillRepeatedly(ReturnRefOfCopy(new_path
));
631 info
.target_path
= new_path
;
632 item(0).NotifyObserversDownloadUpdated();
633 ExpectDownloadUpdated(info
);
636 EXPECT_CALL(item(0), GetEndTime()).WillRepeatedly(Return(new_time
));
637 info
.end_time
= new_time
;
638 item(0).NotifyObserversDownloadUpdated();
639 ExpectDownloadUpdated(info
);
642 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(101));
643 info
.received_bytes
= 101;
644 item(0).NotifyObserversDownloadUpdated();
645 ExpectDownloadUpdated(info
);
648 EXPECT_CALL(item(0), GetTotalBytes()).WillRepeatedly(Return(102));
649 info
.total_bytes
= 102;
650 item(0).NotifyObserversDownloadUpdated();
651 ExpectDownloadUpdated(info
);
654 EXPECT_CALL(item(0), GetETag()).WillRepeatedly(ReturnRefOfCopy(new_etag
));
655 info
.etag
= new_etag
;
656 item(0).NotifyObserversDownloadUpdated();
657 ExpectDownloadUpdated(info
);
660 EXPECT_CALL(item(0), GetLastModifiedTime())
661 .WillRepeatedly(ReturnRefOfCopy(new_last_modifed
));
662 info
.last_modified
= new_last_modifed
;
663 item(0).NotifyObserversDownloadUpdated();
664 ExpectDownloadUpdated(info
);
667 EXPECT_CALL(item(0), GetState())
668 .WillRepeatedly(Return(content::DownloadItem::INTERRUPTED
));
669 info
.state
= content::DownloadItem::INTERRUPTED
;
670 item(0).NotifyObserversDownloadUpdated();
671 ExpectDownloadUpdated(info
);
674 EXPECT_CALL(item(0), GetDangerType())
675 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT
));
676 info
.danger_type
= content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT
;
677 item(0).NotifyObserversDownloadUpdated();
678 ExpectDownloadUpdated(info
);
681 EXPECT_CALL(item(0), GetLastReason())
682 .WillRepeatedly(Return(content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED
));
683 info
.interrupt_reason
= content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED
;
684 item(0).NotifyObserversDownloadUpdated();
685 ExpectDownloadUpdated(info
);
688 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
690 item(0).NotifyObserversDownloadUpdated();
691 ExpectDownloadUpdated(info
);
694 // Test creating a new item, saving it, removing it by setting it Temporary,
695 // changing it without saving it back because it's Temporary, clearing
696 // IsTemporary, saving it back, changing it, saving it back because it isn't
697 // Temporary anymore.
698 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_Temporary
) {
699 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
700 // OnDownloadRemoved.
701 CreateDownloadHistory(scoped_ptr
<InfoVector
>(new InfoVector()));
703 history::DownloadRow info
;
704 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
705 "http://example.com/bar.pdf",
706 "http://example.com/referrer.html",
709 // Pretend the manager just created |item|.
710 CallOnDownloadCreated(0);
711 ExpectDownloadCreated(info
);
712 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
714 // Pretend the item was marked temporary. DownloadHistory should remove it
715 // from history and start ignoring it.
716 EXPECT_CALL(item(0), IsTemporary()).WillRepeatedly(Return(true));
717 item(0).NotifyObserversDownloadUpdated();
720 ExpectDownloadsRemoved(ids
);
722 // Change something that would make DownloadHistory call UpdateDownload if the
723 // item weren't temporary.
724 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(4200));
725 item(0).NotifyObserversDownloadUpdated();
726 ExpectNoDownloadUpdated();
728 // Changing a temporary item back to a non-temporary item should make
729 // DownloadHistory call CreateDownload.
730 EXPECT_CALL(item(0), IsTemporary()).WillRepeatedly(Return(false));
731 item(0).NotifyObserversDownloadUpdated();
732 info
.received_bytes
= 4200;
733 ExpectDownloadCreated(info
);
734 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
736 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(100));
737 item(0).NotifyObserversDownloadUpdated();
738 info
.received_bytes
= 100;
739 ExpectDownloadUpdated(info
);
742 // Test removing downloads while they're still being added.
743 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_RemoveWhileAdding
) {
744 CreateDownloadHistory(scoped_ptr
<InfoVector
>(new InfoVector()));
746 history::DownloadRow info
;
747 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
748 "http://example.com/bar.pdf",
749 "http://example.com/referrer.html",
752 // Instruct CreateDownload() to not callback to DownloadHistory immediately,
753 // but to wait for FinishCreateDownload().
754 set_slow_create_download(true);
756 // Pretend the manager just created |item|.
757 CallOnDownloadCreated(0);
758 ExpectDownloadCreated(info
);
759 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
761 // Call OnDownloadRemoved before calling back to DownloadHistory::ItemAdded().
762 // Instead of calling RemoveDownloads() immediately, DownloadHistory should
763 // add the item's id to removed_while_adding_. Then, ItemAdded should
764 // immediately remove the item's record from history.
765 item(0).NotifyObserversDownloadRemoved();
766 EXPECT_CALL(manager(), GetDownload(item(0).GetId()))
767 .WillRepeatedly(Return(static_cast<content::DownloadItem
*>(NULL
)));
768 ExpectNoDownloadsRemoved();
769 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
771 // Now callback to DownloadHistory::ItemAdded(), and expect a call to
772 // RemoveDownloads() for the item that was removed while it was being added.
773 FinishCreateDownload();
776 ExpectDownloadsRemoved(ids
);
777 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
780 // Test loading multiple items from the database and removing them all.
781 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_Multiple
) {
782 // Load a download from history, create the item, OnDownloadCreated,
783 // OnDownloadUpdated, OnDownloadRemoved.
784 history::DownloadRow info0
, info1
;
785 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
786 "http://example.com/bar.pdf",
787 "http://example.com/referrer.html",
789 InitBasicItem(FILE_PATH_LITERAL("/foo/qux.pdf"),
790 "http://example.com/qux.pdf",
791 "http://example.com/referrer1.html",
794 scoped_ptr
<InfoVector
> infos(new InfoVector());
795 infos
->push_back(info0
);
796 infos
->push_back(info1
);
797 CreateDownloadHistory(infos
.Pass());
798 ExpectNoDownloadCreated();
801 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
802 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(1)));
804 // Pretend that the user removed both items.
806 ids
.insert(info0
.id
);
807 ids
.insert(info1
.id
);
808 item(0).NotifyObserversDownloadRemoved();
809 item(1).NotifyObserversDownloadRemoved();
810 ExpectDownloadsRemoved(ids
);
813 // Test what happens when HistoryService/CreateDownload::CreateDownload() fails.
814 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_CreateFailed
) {
815 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
816 // OnDownloadRemoved.
817 CreateDownloadHistory(scoped_ptr
<InfoVector
>(new InfoVector()));
819 history::DownloadRow info
;
820 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
821 "http://example.com/bar.pdf",
822 "http://example.com/referrer.html",
825 FailCreateDownload();
826 // Pretend the manager just created |item|.
827 CallOnDownloadCreated(0);
828 ExpectDownloadCreated(info
);
829 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
831 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(100));
832 item(0).NotifyObserversDownloadUpdated();
833 info
.received_bytes
= 100;
834 ExpectDownloadCreated(info
);
835 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
838 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_UpdateWhileAdding
) {
839 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
840 // OnDownloadRemoved.
841 CreateDownloadHistory(scoped_ptr
<InfoVector
>(new InfoVector()));
843 history::DownloadRow info
;
844 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
845 "http://example.com/bar.pdf",
846 "http://example.com/referrer.html",
849 // Instruct CreateDownload() to not callback to DownloadHistory immediately,
850 // but to wait for FinishCreateDownload().
851 set_slow_create_download(true);
853 // Pretend the manager just created |item|.
854 CallOnDownloadCreated(0);
855 ExpectDownloadCreated(info
);
856 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
858 // Pretend that something changed on the item.
859 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
860 item(0).NotifyObserversDownloadUpdated();
862 FinishCreateDownload();
863 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
865 // ItemAdded should call OnDownloadUpdated, which should detect that the item
866 // changed while it was being added and call UpdateDownload immediately.
868 ExpectDownloadUpdated(info
);
871 } // anonymous namespace