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.
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(OS_ANDROID)
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
.start_time
.ToTimeT(), right
.start_time
.ToTimeT());
46 EXPECT_EQ(left
.end_time
.ToTimeT(), right
.end_time
.ToTimeT());
47 EXPECT_EQ(left
.etag
, right
.etag
);
48 EXPECT_EQ(left
.last_modified
, right
.last_modified
);
49 EXPECT_EQ(left
.received_bytes
, right
.received_bytes
);
50 EXPECT_EQ(left
.total_bytes
, right
.total_bytes
);
51 EXPECT_EQ(left
.state
, right
.state
);
52 EXPECT_EQ(left
.danger_type
, right
.danger_type
);
53 EXPECT_EQ(left
.id
, right
.id
);
54 EXPECT_EQ(left
.opened
, right
.opened
);
55 EXPECT_EQ(left
.by_ext_id
, right
.by_ext_id
);
56 EXPECT_EQ(left
.by_ext_name
, right
.by_ext_name
);
59 typedef DownloadHistory::IdSet IdSet
;
60 typedef std::vector
<history::DownloadRow
> InfoVector
;
61 typedef testing::StrictMock
<content::MockDownloadItem
> StrictMockDownloadItem
;
63 class FakeHistoryAdapter
: public DownloadHistory::HistoryAdapter
{
66 : DownloadHistory::HistoryAdapter(NULL
),
67 slow_create_download_(false),
68 fail_create_download_(false) {
71 virtual ~FakeHistoryAdapter() {}
73 virtual void QueryDownloads(
74 const HistoryService::DownloadQueryCallback
& callback
) OVERRIDE
{
75 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
76 content::BrowserThread::PostTask(content::BrowserThread::UI
, FROM_HERE
,
77 base::Bind(&FakeHistoryAdapter::QueryDownloadsDone
,
78 base::Unretained(this), callback
));
81 void QueryDownloadsDone(
82 const HistoryService::DownloadQueryCallback
& callback
) {
83 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
84 CHECK(expect_query_downloads_
.get());
85 callback
.Run(expect_query_downloads_
.Pass());
88 void set_slow_create_download(bool slow
) { slow_create_download_
= slow
; }
90 virtual void CreateDownload(
91 const history::DownloadRow
& info
,
92 const HistoryService::DownloadCreateCallback
& callback
) OVERRIDE
{
93 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
94 create_download_info_
= info
;
95 // Must not call CreateDownload() again before FinishCreateDownload()!
96 DCHECK(create_download_callback_
.is_null());
97 create_download_callback_
= base::Bind(callback
, !fail_create_download_
);
98 fail_create_download_
= false;
99 if (!slow_create_download_
)
100 FinishCreateDownload();
103 void FinishCreateDownload() {
104 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
105 create_download_callback_
.Run();
106 create_download_callback_
.Reset();
109 virtual void UpdateDownload(
110 const history::DownloadRow
& info
) OVERRIDE
{
111 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
112 update_download_
= info
;
115 virtual void RemoveDownloads(const IdSet
& ids
) OVERRIDE
{
116 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
117 for (IdSet::const_iterator it
= ids
.begin();
118 it
!= ids
.end(); ++it
) {
119 remove_downloads_
.insert(*it
);
123 void ExpectWillQueryDownloads(scoped_ptr
<InfoVector
> infos
) {
124 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
125 expect_query_downloads_
= infos
.Pass();
128 void ExpectQueryDownloadsDone() {
129 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
130 EXPECT_TRUE(NULL
== expect_query_downloads_
.get());
133 void FailCreateDownload() {
134 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
135 fail_create_download_
= true;
138 void ExpectDownloadCreated(
139 const history::DownloadRow
& info
) {
140 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
141 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
142 CheckInfoEqual(info
, create_download_info_
);
143 create_download_info_
= history::DownloadRow();
146 void ExpectNoDownloadCreated() {
147 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
148 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
149 CheckInfoEqual(history::DownloadRow(), create_download_info_
);
152 void ExpectDownloadUpdated(const history::DownloadRow
& info
) {
153 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
154 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
155 CheckInfoEqual(update_download_
, info
);
156 update_download_
= history::DownloadRow();
159 void ExpectNoDownloadUpdated() {
160 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
161 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
162 CheckInfoEqual(history::DownloadRow(), update_download_
);
165 void ExpectNoDownloadsRemoved() {
166 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
167 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
168 EXPECT_EQ(0, static_cast<int>(remove_downloads_
.size()));
171 void ExpectDownloadsRemoved(const IdSet
& ids
) {
172 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
173 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
174 IdSet differences
= base::STLSetDifference
<IdSet
>(ids
, remove_downloads_
);
175 for (IdSet::const_iterator different
= differences
.begin();
176 different
!= differences
.end(); ++different
) {
177 EXPECT_TRUE(false) << *different
;
179 remove_downloads_
.clear();
183 bool slow_create_download_
;
184 bool fail_create_download_
;
185 base::Closure create_download_callback_
;
186 history::DownloadRow update_download_
;
187 scoped_ptr
<InfoVector
> expect_query_downloads_
;
188 IdSet remove_downloads_
;
189 history::DownloadRow create_download_info_
;
191 DISALLOW_COPY_AND_ASSIGN(FakeHistoryAdapter
);
194 class DownloadHistoryTest
: public testing::Test
{
196 DownloadHistoryTest()
197 : ui_thread_(content::BrowserThread::UI
, &loop_
),
198 manager_(new content::MockDownloadManager()),
200 manager_observer_(NULL
),
201 item_observer_(NULL
),
202 download_created_index_(0) {}
203 virtual ~DownloadHistoryTest() {
204 STLDeleteElements(&items_
);
208 virtual void TearDown() OVERRIDE
{
209 download_history_
.reset();
212 content::MockDownloadManager
& manager() { return *manager_
.get(); }
213 content::MockDownloadItem
& item(size_t index
) { return *items_
[index
]; }
215 void SetManagerObserver(
216 content::DownloadManager::Observer
* manager_observer
) {
217 manager_observer_
= manager_observer
;
219 content::DownloadManager::Observer
* manager_observer() {
220 return manager_observer_
;
223 // Relies on the same object observing all download items.
224 void SetItemObserver(
225 content::DownloadItem::Observer
* item_observer
) {
226 item_observer_
= item_observer
;
228 content::DownloadItem::Observer
* item_observer() {
229 return item_observer_
;
232 void ExpectWillQueryDownloads(scoped_ptr
<InfoVector
> infos
) {
233 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
235 EXPECT_CALL(manager(), AddObserver(_
)).WillOnce(WithArg
<0>(Invoke(
236 this, &DownloadHistoryTest::SetManagerObserver
)));
237 EXPECT_CALL(manager(), RemoveObserver(_
));
238 download_created_index_
= 0;
239 for (size_t index
= 0; index
< infos
->size(); ++index
) {
240 content::MockDownloadManager::CreateDownloadItemAdapter
adapter(
242 infos
->at(index
).current_path
,
243 infos
->at(index
).target_path
,
244 infos
->at(index
).url_chain
,
245 infos
->at(index
).referrer_url
,
246 infos
->at(index
).start_time
,
247 infos
->at(index
).end_time
,
248 infos
->at(index
).etag
,
249 infos
->at(index
).last_modified
,
250 infos
->at(index
).received_bytes
,
251 infos
->at(index
).total_bytes
,
252 infos
->at(index
).state
,
253 infos
->at(index
).danger_type
,
254 infos
->at(index
).interrupt_reason
,
255 infos
->at(index
).opened
);
256 EXPECT_CALL(manager(), MockCreateDownloadItem(adapter
))
259 this, &DownloadHistoryTest::CallOnDownloadCreatedInOrder
),
260 Return(&item(index
))));
262 EXPECT_CALL(manager(), CheckForHistoryFilesRemoval());
263 history_
= new FakeHistoryAdapter();
264 history_
->ExpectWillQueryDownloads(infos
.Pass());
265 EXPECT_CALL(*manager_
.get(), GetAllDownloads(_
)).WillRepeatedly(Return());
266 download_history_
.reset(new DownloadHistory(
267 &manager(), scoped_ptr
<DownloadHistory::HistoryAdapter
>(history_
)));
268 content::RunAllPendingInMessageLoop(content::BrowserThread::UI
);
269 history_
->ExpectQueryDownloadsDone();
272 void CallOnDownloadCreated(size_t index
) {
273 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
274 manager_observer()->OnDownloadCreated(&manager(), &item(index
));
277 void CallOnDownloadCreatedInOrder() {
278 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
279 // Gmock doesn't appear to support something like InvokeWithTheseArgs. Maybe
280 // gmock needs to learn about base::Callback.
281 CallOnDownloadCreated(download_created_index_
++);
284 void set_slow_create_download(bool slow
) {
285 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
286 history_
->set_slow_create_download(slow
);
289 void FinishCreateDownload() {
290 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
291 history_
->FinishCreateDownload();
294 void FailCreateDownload() {
295 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
296 history_
->FailCreateDownload();
299 void ExpectDownloadCreated(
300 const history::DownloadRow
& info
) {
301 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
302 history_
->ExpectDownloadCreated(info
);
305 void ExpectNoDownloadCreated() {
306 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
307 history_
->ExpectNoDownloadCreated();
310 void ExpectDownloadUpdated(const history::DownloadRow
& info
) {
311 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
312 history_
->ExpectDownloadUpdated(info
);
315 void ExpectNoDownloadUpdated() {
316 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
317 history_
->ExpectNoDownloadUpdated();
320 void ExpectNoDownloadsRemoved() {
321 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
322 history_
->ExpectNoDownloadsRemoved();
325 void ExpectDownloadsRemoved(const IdSet
& ids
) {
326 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
327 history_
->ExpectDownloadsRemoved(ids
);
330 void InitBasicItem(const base::FilePath::CharType
* path
,
331 const char* url_string
,
332 const char* referrer_string
,
333 history::DownloadRow
* info
) {
334 GURL
url(url_string
);
335 GURL
referrer(referrer_string
);
336 std::vector
<GURL
> url_chain
;
337 url_chain
.push_back(url
);
338 InitItem(static_cast<uint32
>(items_
.size() + 1),
339 base::FilePath(path
),
340 base::FilePath(path
),
343 (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
344 (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
349 content::DownloadItem::COMPLETE
,
350 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
,
351 content::DOWNLOAD_INTERRUPT_REASON_NONE
,
360 const base::FilePath
& current_path
,
361 const base::FilePath
& target_path
,
362 const std::vector
<GURL
>& url_chain
,
363 const GURL
& referrer
,
364 const base::Time
& start_time
,
365 const base::Time
& end_time
,
366 const std::string
& etag
,
367 const std::string
& last_modified
,
368 int64 received_bytes
,
370 content::DownloadItem::DownloadState state
,
371 content::DownloadDangerType danger_type
,
372 content::DownloadInterruptReason interrupt_reason
,
374 const std::string
& by_extension_id
,
375 const std::string
& by_extension_name
,
376 history::DownloadRow
* info
) {
377 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
379 size_t index
= items_
.size();
380 StrictMockDownloadItem
* mock_item
= new StrictMockDownloadItem();
381 items_
.push_back(mock_item
);
383 info
->current_path
= current_path
;
384 info
->target_path
= target_path
;
385 info
->url_chain
= url_chain
;
386 info
->referrer_url
= referrer
;
387 info
->start_time
= start_time
;
388 info
->end_time
= end_time
;
390 info
->last_modified
= last_modified
;
391 info
->received_bytes
= received_bytes
;
392 info
->total_bytes
= total_bytes
;
394 info
->danger_type
= danger_type
;
395 info
->interrupt_reason
= interrupt_reason
;
397 info
->opened
= opened
;
398 info
->by_ext_id
= by_extension_id
;
399 info
->by_ext_name
= by_extension_name
;
401 EXPECT_CALL(item(index
), GetId()).WillRepeatedly(Return(id
));
402 EXPECT_CALL(item(index
), GetFullPath())
403 .WillRepeatedly(ReturnRefOfCopy(current_path
));
404 EXPECT_CALL(item(index
), GetTargetFilePath())
405 .WillRepeatedly(ReturnRefOfCopy(target_path
));
406 DCHECK_LE(1u, url_chain
.size());
407 EXPECT_CALL(item(index
), GetURL())
408 .WillRepeatedly(ReturnRefOfCopy(url_chain
[0]));
409 EXPECT_CALL(item(index
), GetUrlChain())
410 .WillRepeatedly(ReturnRefOfCopy(url_chain
));
411 EXPECT_CALL(item(index
), GetMimeType())
412 .WillRepeatedly(Return("application/octet-stream"));
413 EXPECT_CALL(item(index
), GetReferrerUrl())
414 .WillRepeatedly(ReturnRefOfCopy(referrer
));
415 EXPECT_CALL(item(index
), GetStartTime()).WillRepeatedly(Return(start_time
));
416 EXPECT_CALL(item(index
), GetEndTime()).WillRepeatedly(Return(end_time
));
417 EXPECT_CALL(item(index
), GetETag()).WillRepeatedly(ReturnRefOfCopy(etag
));
418 EXPECT_CALL(item(index
), GetLastModifiedTime())
419 .WillRepeatedly(ReturnRefOfCopy(last_modified
));
420 EXPECT_CALL(item(index
), GetReceivedBytes())
421 .WillRepeatedly(Return(received_bytes
));
422 EXPECT_CALL(item(index
), GetTotalBytes())
423 .WillRepeatedly(Return(total_bytes
));
424 EXPECT_CALL(item(index
), GetState()).WillRepeatedly(Return(state
));
425 EXPECT_CALL(item(index
), GetDangerType())
426 .WillRepeatedly(Return(danger_type
));
427 EXPECT_CALL(item(index
), GetLastReason())
428 .WillRepeatedly(Return(interrupt_reason
));
429 EXPECT_CALL(item(index
), GetOpened()).WillRepeatedly(Return(opened
));
430 EXPECT_CALL(item(index
), GetTargetDisposition())
432 Return(content::DownloadItem::TARGET_DISPOSITION_OVERWRITE
));
433 EXPECT_CALL(manager(), GetDownload(id
))
434 .WillRepeatedly(Return(&item(index
)));
435 EXPECT_CALL(item(index
), AddObserver(_
))
436 .WillOnce(WithArg
<0>(
437 Invoke(this, &DownloadHistoryTest::SetItemObserver
)));
438 EXPECT_CALL(item(index
), RemoveObserver(_
));
439 EXPECT_CALL(item(index
), IsTemporary()).WillRepeatedly(Return(false));
440 #if !defined(OS_ANDROID)
441 new DownloadedByExtension(&item(index
), by_extension_id
, by_extension_name
);
444 std::vector
<content::DownloadItem
*> items
;
445 for (size_t i
= 0; i
< items_
.size(); ++i
) {
446 items
.push_back(&item(i
));
448 EXPECT_CALL(*manager_
.get(), GetAllDownloads(_
))
449 .WillRepeatedly(SetArgPointee
<0>(items
));
453 base::MessageLoopForUI loop_
;
454 content::TestBrowserThread ui_thread_
;
455 std::vector
<StrictMockDownloadItem
*> items_
;
456 scoped_ptr
<content::MockDownloadManager
> manager_
;
457 FakeHistoryAdapter
* history_
;
458 scoped_ptr
<DownloadHistory
> download_history_
;
459 content::DownloadManager::Observer
* manager_observer_
;
460 content::DownloadItem::Observer
* item_observer_
;
461 size_t download_created_index_
;
463 DISALLOW_COPY_AND_ASSIGN(DownloadHistoryTest
);
466 } // anonymous namespace
468 // Test loading an item from the database, changing it, saving it back, removing
470 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_Load
) {
471 // Load a download from history, create the item, OnDownloadCreated,
472 // OnDownloadUpdated, OnDownloadRemoved.
473 history::DownloadRow info
;
474 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
475 "http://example.com/bar.pdf",
476 "http://example.com/referrer.html",
479 scoped_ptr
<InfoVector
> infos(new InfoVector());
480 infos
->push_back(info
);
481 ExpectWillQueryDownloads(infos
.Pass());
482 ExpectNoDownloadCreated();
484 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
486 // Pretend that something changed on the item.
487 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
488 item_observer()->OnDownloadUpdated(&item(0));
490 ExpectDownloadUpdated(info
);
492 // Pretend that the user removed the item.
495 item_observer()->OnDownloadRemoved(&item(0));
496 ExpectDownloadsRemoved(ids
);
499 // Test creating an item, saving it to the database, changing it, saving it
500 // back, removing it.
501 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_Create
) {
502 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
503 // OnDownloadRemoved.
504 ExpectWillQueryDownloads(scoped_ptr
<InfoVector
>(new InfoVector()));
506 history::DownloadRow info
;
507 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
508 "http://example.com/bar.pdf",
509 "http://example.com/referrer.html",
512 // Pretend the manager just created |item|.
513 CallOnDownloadCreated(0);
514 ExpectDownloadCreated(info
);
515 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
517 // Pretend that something changed on the item.
518 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
519 item_observer()->OnDownloadUpdated(&item(0));
521 ExpectDownloadUpdated(info
);
523 // Pretend that the user removed the item.
526 item_observer()->OnDownloadRemoved(&item(0));
527 ExpectDownloadsRemoved(ids
);
530 // Test that changes to persisted fields in a DownloadItem triggers database
532 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_Update
) {
533 ExpectWillQueryDownloads(scoped_ptr
<InfoVector
>(new InfoVector()));
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 CallOnDownloadCreated(0);
541 ExpectDownloadCreated(info
);
542 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
544 base::FilePath
new_path(FILE_PATH_LITERAL("/foo/baz.txt"));
545 base::Time
new_time(base::Time::Now());
546 std::string
new_etag("new etag");
547 std::string
new_last_modifed("new last modified");
550 EXPECT_CALL(item(0), GetFullPath()).WillRepeatedly(ReturnRefOfCopy(new_path
));
551 info
.current_path
= new_path
;
552 item_observer()->OnDownloadUpdated(&item(0));
553 ExpectDownloadUpdated(info
);
556 EXPECT_CALL(item(0), GetTargetFilePath())
557 .WillRepeatedly(ReturnRefOfCopy(new_path
));
558 info
.target_path
= new_path
;
559 item_observer()->OnDownloadUpdated(&item(0));
560 ExpectDownloadUpdated(info
);
563 EXPECT_CALL(item(0), GetEndTime()).WillRepeatedly(Return(new_time
));
564 info
.end_time
= new_time
;
565 item_observer()->OnDownloadUpdated(&item(0));
566 ExpectDownloadUpdated(info
);
569 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(101));
570 info
.received_bytes
= 101;
571 item_observer()->OnDownloadUpdated(&item(0));
572 ExpectDownloadUpdated(info
);
575 EXPECT_CALL(item(0), GetTotalBytes()).WillRepeatedly(Return(102));
576 info
.total_bytes
= 102;
577 item_observer()->OnDownloadUpdated(&item(0));
578 ExpectDownloadUpdated(info
);
581 EXPECT_CALL(item(0), GetETag()).WillRepeatedly(ReturnRefOfCopy(new_etag
));
582 info
.etag
= new_etag
;
583 item_observer()->OnDownloadUpdated(&item(0));
584 ExpectDownloadUpdated(info
);
587 EXPECT_CALL(item(0), GetLastModifiedTime())
588 .WillRepeatedly(ReturnRefOfCopy(new_last_modifed
));
589 info
.last_modified
= new_last_modifed
;
590 item_observer()->OnDownloadUpdated(&item(0));
591 ExpectDownloadUpdated(info
);
594 EXPECT_CALL(item(0), GetState())
595 .WillRepeatedly(Return(content::DownloadItem::INTERRUPTED
));
596 info
.state
= content::DownloadItem::INTERRUPTED
;
597 item_observer()->OnDownloadUpdated(&item(0));
598 ExpectDownloadUpdated(info
);
601 EXPECT_CALL(item(0), GetDangerType())
602 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT
));
603 info
.danger_type
= content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT
;
604 item_observer()->OnDownloadUpdated(&item(0));
605 ExpectDownloadUpdated(info
);
608 EXPECT_CALL(item(0), GetLastReason())
609 .WillRepeatedly(Return(content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED
));
610 info
.interrupt_reason
= content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED
;
611 item_observer()->OnDownloadUpdated(&item(0));
612 ExpectDownloadUpdated(info
);
615 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
617 item_observer()->OnDownloadUpdated(&item(0));
618 ExpectDownloadUpdated(info
);
621 // Test creating a new item, saving it, removing it by setting it Temporary,
622 // changing it without saving it back because it's Temporary, clearing
623 // IsTemporary, saving it back, changing it, saving it back because it isn't
624 // Temporary anymore.
625 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_Temporary
) {
626 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
627 // OnDownloadRemoved.
628 ExpectWillQueryDownloads(scoped_ptr
<InfoVector
>(new InfoVector()));
630 history::DownloadRow info
;
631 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
632 "http://example.com/bar.pdf",
633 "http://example.com/referrer.html",
636 // Pretend the manager just created |item|.
637 CallOnDownloadCreated(0);
638 ExpectDownloadCreated(info
);
639 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
641 // Pretend the item was marked temporary. DownloadHistory should remove it
642 // from history and start ignoring it.
643 EXPECT_CALL(item(0), IsTemporary()).WillRepeatedly(Return(true));
644 item_observer()->OnDownloadUpdated(&item(0));
647 ExpectDownloadsRemoved(ids
);
649 // Change something that would make DownloadHistory call UpdateDownload if the
650 // item weren't temporary.
651 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(4200));
652 item_observer()->OnDownloadUpdated(&item(0));
653 ExpectNoDownloadUpdated();
655 // Changing a temporary item back to a non-temporary item should make
656 // DownloadHistory call CreateDownload.
657 EXPECT_CALL(item(0), IsTemporary()).WillRepeatedly(Return(false));
658 item_observer()->OnDownloadUpdated(&item(0));
659 info
.received_bytes
= 4200;
660 ExpectDownloadCreated(info
);
661 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
663 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(100));
664 item_observer()->OnDownloadUpdated(&item(0));
665 info
.received_bytes
= 100;
666 ExpectDownloadUpdated(info
);
669 // Test removing downloads while they're still being added.
670 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_RemoveWhileAdding
) {
671 ExpectWillQueryDownloads(scoped_ptr
<InfoVector
>(new InfoVector()));
673 history::DownloadRow info
;
674 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
675 "http://example.com/bar.pdf",
676 "http://example.com/referrer.html",
679 // Instruct CreateDownload() to not callback to DownloadHistory immediately,
680 // but to wait for FinishCreateDownload().
681 set_slow_create_download(true);
683 // Pretend the manager just created |item|.
684 CallOnDownloadCreated(0);
685 ExpectDownloadCreated(info
);
686 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
688 // Call OnDownloadRemoved before calling back to DownloadHistory::ItemAdded().
689 // Instead of calling RemoveDownloads() immediately, DownloadHistory should
690 // add the item's id to removed_while_adding_. Then, ItemAdded should
691 // immediately remove the item's record from history.
692 item_observer()->OnDownloadRemoved(&item(0));
693 EXPECT_CALL(manager(), GetDownload(item(0).GetId()))
694 .WillRepeatedly(Return(static_cast<content::DownloadItem
*>(NULL
)));
695 ExpectNoDownloadsRemoved();
696 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
698 // Now callback to DownloadHistory::ItemAdded(), and expect a call to
699 // RemoveDownloads() for the item that was removed while it was being added.
700 FinishCreateDownload();
703 ExpectDownloadsRemoved(ids
);
704 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
707 // Test loading multiple items from the database and removing them all.
708 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_Multiple
) {
709 // Load a download from history, create the item, OnDownloadCreated,
710 // OnDownloadUpdated, OnDownloadRemoved.
711 history::DownloadRow info0
, info1
;
712 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
713 "http://example.com/bar.pdf",
714 "http://example.com/referrer.html",
716 InitBasicItem(FILE_PATH_LITERAL("/foo/qux.pdf"),
717 "http://example.com/qux.pdf",
718 "http://example.com/referrer1.html",
721 scoped_ptr
<InfoVector
> infos(new InfoVector());
722 infos
->push_back(info0
);
723 infos
->push_back(info1
);
724 ExpectWillQueryDownloads(infos
.Pass());
725 ExpectNoDownloadCreated();
728 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
729 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(1)));
731 // Pretend that the user removed both items.
733 ids
.insert(info0
.id
);
734 ids
.insert(info1
.id
);
735 item_observer()->OnDownloadRemoved(&item(0));
736 item_observer()->OnDownloadRemoved(&item(1));
737 ExpectDownloadsRemoved(ids
);
740 // Test what happens when HistoryService/CreateDownload::CreateDownload() fails.
741 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_CreateFailed
) {
742 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
743 // OnDownloadRemoved.
744 ExpectWillQueryDownloads(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 FailCreateDownload();
753 // Pretend the manager just created |item|.
754 CallOnDownloadCreated(0);
755 ExpectDownloadCreated(info
);
756 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
758 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(100));
759 item_observer()->OnDownloadUpdated(&item(0));
760 info
.received_bytes
= 100;
761 ExpectDownloadCreated(info
);
762 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
765 TEST_F(DownloadHistoryTest
, DownloadHistoryTest_UpdateWhileAdding
) {
766 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
767 // OnDownloadRemoved.
768 ExpectWillQueryDownloads(scoped_ptr
<InfoVector
>(new InfoVector()));
770 history::DownloadRow info
;
771 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
772 "http://example.com/bar.pdf",
773 "http://example.com/referrer.html",
776 // Instruct CreateDownload() to not callback to DownloadHistory immediately,
777 // but to wait for FinishCreateDownload().
778 set_slow_create_download(true);
780 // Pretend the manager just created |item|.
781 CallOnDownloadCreated(0);
782 ExpectDownloadCreated(info
);
783 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
785 // Pretend that something changed on the item.
786 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
787 item_observer()->OnDownloadUpdated(&item(0));
789 FinishCreateDownload();
790 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
792 // ItemAdded should call OnDownloadUpdated, which should detect that the item
793 // changed while it was being added and call UpdateDownload immediately.
795 ExpectDownloadUpdated(info
);