Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / download / download_history_unittest.cc
blobdb441eda78751fdd6e98aab1325c0c53eabb6f81
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 <vector>
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 "components/history/content/browser/download_constants_utils.h"
12 #include "components/history/core/browser/download_constants.h"
13 #include "components/history/core/browser/download_row.h"
14 #include "components/history/core/browser/history_service.h"
15 #include "content/public/test/mock_download_item.h"
16 #include "content/public/test/mock_download_manager.h"
17 #include "content/public/test/test_browser_thread.h"
18 #include "content/public/test/test_utils.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 #if defined(ENABLE_EXTENSIONS)
22 #include "chrome/browser/extensions/api/downloads/downloads_api.h"
23 #endif
25 using testing::DoAll;
26 using testing::Invoke;
27 using testing::Return;
28 using testing::ReturnRefOfCopy;
29 using testing::SetArgPointee;
30 using testing::WithArg;
31 using testing::_;
33 namespace {
35 void CheckInfoEqual(const history::DownloadRow& left,
36 const history::DownloadRow& right) {
37 EXPECT_EQ(left.current_path.value(), right.current_path.value());
38 EXPECT_EQ(left.target_path.value(), right.target_path.value());
39 EXPECT_EQ(left.url_chain.size(), right.url_chain.size());
40 for (unsigned int i = 0;
41 i < left.url_chain.size() && i < right.url_chain.size();
42 ++i) {
43 EXPECT_EQ(left.url_chain[i].spec(), right.url_chain[i].spec());
45 EXPECT_EQ(left.referrer_url.spec(), right.referrer_url.spec());
46 EXPECT_EQ(left.mime_type, right.mime_type);
47 EXPECT_EQ(left.original_mime_type, right.original_mime_type);
48 EXPECT_EQ(left.start_time.ToTimeT(), right.start_time.ToTimeT());
49 EXPECT_EQ(left.end_time.ToTimeT(), right.end_time.ToTimeT());
50 EXPECT_EQ(left.etag, right.etag);
51 EXPECT_EQ(left.last_modified, right.last_modified);
52 EXPECT_EQ(left.received_bytes, right.received_bytes);
53 EXPECT_EQ(left.total_bytes, right.total_bytes);
54 EXPECT_EQ(left.state, right.state);
55 EXPECT_EQ(left.danger_type, right.danger_type);
56 EXPECT_EQ(left.id, right.id);
57 EXPECT_EQ(left.opened, right.opened);
58 EXPECT_EQ(left.by_ext_id, right.by_ext_id);
59 EXPECT_EQ(left.by_ext_name, right.by_ext_name);
62 typedef DownloadHistory::IdSet IdSet;
63 typedef std::vector<history::DownloadRow> InfoVector;
64 typedef testing::StrictMock<content::MockDownloadItem> StrictMockDownloadItem;
66 class FakeHistoryAdapter : public DownloadHistory::HistoryAdapter {
67 public:
68 FakeHistoryAdapter()
69 : DownloadHistory::HistoryAdapter(NULL),
70 slow_create_download_(false),
71 fail_create_download_(false) {
74 ~FakeHistoryAdapter() override {}
76 void QueryDownloads(
77 const history::HistoryService::DownloadQueryCallback& callback) override {
78 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
79 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
80 base::Bind(&FakeHistoryAdapter::QueryDownloadsDone,
81 base::Unretained(this), callback));
84 void QueryDownloadsDone(
85 const history::HistoryService::DownloadQueryCallback& callback) {
86 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
87 CHECK(expect_query_downloads_.get());
88 callback.Run(expect_query_downloads_.Pass());
91 void set_slow_create_download(bool slow) { slow_create_download_ = slow; }
93 void CreateDownload(const history::DownloadRow& info,
94 const history::HistoryService::DownloadCreateCallback&
95 callback) override {
96 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
97 create_download_info_ = info;
98 // Must not call CreateDownload() again before FinishCreateDownload()!
99 DCHECK(create_download_callback_.is_null());
100 create_download_callback_ = base::Bind(callback, !fail_create_download_);
101 fail_create_download_ = false;
102 if (!slow_create_download_)
103 FinishCreateDownload();
106 void FinishCreateDownload() {
107 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
108 create_download_callback_.Run();
109 create_download_callback_.Reset();
112 void UpdateDownload(const history::DownloadRow& info) override {
113 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
114 update_download_ = info;
117 void RemoveDownloads(const IdSet& ids) override {
118 DCHECK_CURRENTLY_ON(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_CURRENTLY_ON(content::BrowserThread::UI);
127 expect_query_downloads_ = infos.Pass();
130 void ExpectQueryDownloadsDone() {
131 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
132 EXPECT_TRUE(NULL == expect_query_downloads_.get());
135 void FailCreateDownload() {
136 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
137 fail_create_download_ = true;
140 void ExpectDownloadCreated(
141 const history::DownloadRow& info) {
142 DCHECK_CURRENTLY_ON(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_CURRENTLY_ON(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_CURRENTLY_ON(content::BrowserThread::UI);
156 content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
157 CheckInfoEqual(update_download_, info);
158 update_download_ = history::DownloadRow();
161 void ExpectNoDownloadUpdated() {
162 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
163 content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
164 CheckInfoEqual(history::DownloadRow(), update_download_);
167 void ExpectNoDownloadsRemoved() {
168 DCHECK_CURRENTLY_ON(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_CURRENTLY_ON(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();
184 private:
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 {
197 public:
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()),
204 history_(NULL),
205 manager_observer_(NULL),
206 download_created_index_(0) {}
207 ~DownloadHistoryTest() override { STLDeleteElements(&items_); }
209 protected:
210 void TearDown() override { download_history_.reset(); }
212 content::MockDownloadManager& manager() { return *manager_.get(); }
213 content::MockDownloadItem& item(size_t index) { return *items_[index]; }
214 DownloadHistory* download_history() { return download_history_.get(); }
216 void SetManagerObserver(
217 content::DownloadManager::Observer* manager_observer) {
218 manager_observer_ = manager_observer;
220 content::DownloadManager::Observer* manager_observer() {
221 return manager_observer_;
224 void CreateDownloadHistory(scoped_ptr<InfoVector> infos) {
225 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
226 CHECK(infos.get());
227 EXPECT_CALL(manager(), AddObserver(_)).WillOnce(WithArg<0>(Invoke(
228 this, &DownloadHistoryTest::SetManagerObserver)));
229 EXPECT_CALL(manager(), RemoveObserver(_));
230 download_created_index_ = 0;
231 for (size_t index = 0; index < infos->size(); ++index) {
232 const history::DownloadRow& row = infos->at(index);
233 content::MockDownloadManager::CreateDownloadItemAdapter adapter(
234 history::ToContentDownloadId(row.id),
235 row.current_path,
236 row.target_path,
237 row.url_chain,
238 row.referrer_url,
239 row.mime_type,
240 row.original_mime_type,
241 row.start_time,
242 row.end_time,
243 row.etag,
244 row.last_modified,
245 row.received_bytes,
246 row.total_bytes,
247 history::ToContentDownloadState(row.state),
248 history::ToContentDownloadDangerType(row.danger_type),
249 history::ToContentDownloadInterruptReason(row.interrupt_reason),
250 row.opened);
251 EXPECT_CALL(manager(), MockCreateDownloadItem(adapter))
252 .WillOnce(DoAll(
253 InvokeWithoutArgs(
254 this, &DownloadHistoryTest::CallOnDownloadCreatedInOrder),
255 Return(&item(index))));
257 EXPECT_CALL(manager(), CheckForHistoryFilesRemoval());
258 history_ = new FakeHistoryAdapter();
259 history_->ExpectWillQueryDownloads(infos.Pass());
260 EXPECT_CALL(*manager_.get(), GetAllDownloads(_)).WillRepeatedly(Return());
261 download_history_.reset(new DownloadHistory(
262 &manager(), scoped_ptr<DownloadHistory::HistoryAdapter>(history_)));
263 content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
264 history_->ExpectQueryDownloadsDone();
267 void CallOnDownloadCreated(size_t index) {
268 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
269 if (!pre_on_create_handler_.is_null())
270 pre_on_create_handler_.Run(&item(index));
271 manager_observer()->OnDownloadCreated(&manager(), &item(index));
272 if (!post_on_create_handler_.is_null())
273 post_on_create_handler_.Run(&item(index));
276 void CallOnDownloadCreatedInOrder() {
277 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
278 // Gmock doesn't appear to support something like InvokeWithTheseArgs. Maybe
279 // gmock needs to learn about base::Callback.
280 CallOnDownloadCreated(download_created_index_++);
283 void set_slow_create_download(bool slow) {
284 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
285 history_->set_slow_create_download(slow);
288 void FinishCreateDownload() {
289 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
290 history_->FinishCreateDownload();
293 void FailCreateDownload() {
294 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
295 history_->FailCreateDownload();
298 void ExpectDownloadCreated(
299 const history::DownloadRow& info) {
300 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
301 history_->ExpectDownloadCreated(info);
304 void ExpectNoDownloadCreated() {
305 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
306 history_->ExpectNoDownloadCreated();
309 void ExpectDownloadUpdated(const history::DownloadRow& info) {
310 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
311 history_->ExpectDownloadUpdated(info);
314 void ExpectNoDownloadUpdated() {
315 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
316 history_->ExpectNoDownloadUpdated();
319 void ExpectNoDownloadsRemoved() {
320 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
321 history_->ExpectNoDownloadsRemoved();
324 void ExpectDownloadsRemoved(const IdSet& ids) {
325 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
326 history_->ExpectDownloadsRemoved(ids);
329 void ExpectDownloadsRestoredFromHistory(bool expected_value) {
330 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
331 pre_on_create_handler_ =
332 base::Bind(&DownloadHistoryTest::CheckDownloadWasRestoredFromHistory,
333 base::Unretained(this),
334 expected_value);
335 post_on_create_handler_ =
336 base::Bind(&DownloadHistoryTest::CheckDownloadWasRestoredFromHistory,
337 base::Unretained(this),
338 expected_value);
341 void InitBasicItem(const base::FilePath::CharType* path,
342 const char* url_string,
343 const char* referrer_string,
344 history::DownloadRow* info) {
345 GURL url(url_string);
346 GURL referrer(referrer_string);
347 std::vector<GURL> url_chain;
348 url_chain.push_back(url);
349 InitItem(static_cast<uint32>(items_.size() + 1),
350 base::FilePath(path),
351 base::FilePath(path),
352 url_chain,
353 referrer,
354 "application/octet-stream",
355 "application/octet-stream",
356 (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
357 (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
358 "Etag",
359 "abc",
360 100,
361 100,
362 content::DownloadItem::COMPLETE,
363 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
364 content::DOWNLOAD_INTERRUPT_REASON_NONE,
365 false,
366 std::string(),
367 std::string(),
368 info);
371 void InitItem(
372 uint32 id,
373 const base::FilePath& current_path,
374 const base::FilePath& target_path,
375 const std::vector<GURL>& url_chain,
376 const GURL& referrer,
377 const std::string& mime_type,
378 const std::string& original_mime_type,
379 const base::Time& start_time,
380 const base::Time& end_time,
381 const std::string& etag,
382 const std::string& last_modified,
383 int64 received_bytes,
384 int64 total_bytes,
385 content::DownloadItem::DownloadState state,
386 content::DownloadDangerType danger_type,
387 content::DownloadInterruptReason interrupt_reason,
388 bool opened,
389 const std::string& by_extension_id,
390 const std::string& by_extension_name,
391 history::DownloadRow* info) {
392 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
394 size_t index = items_.size();
395 StrictMockDownloadItem* mock_item = new StrictMockDownloadItem();
396 items_.push_back(mock_item);
398 info->current_path = current_path;
399 info->target_path = target_path;
400 info->url_chain = url_chain;
401 info->referrer_url = referrer;
402 info->mime_type = mime_type;
403 info->original_mime_type = original_mime_type;
404 info->start_time = start_time;
405 info->end_time = end_time;
406 info->etag = etag;
407 info->last_modified = last_modified;
408 info->received_bytes = received_bytes;
409 info->total_bytes = total_bytes;
410 info->state = history::ToHistoryDownloadState(state);
411 info->danger_type = history::ToHistoryDownloadDangerType(danger_type);
412 info->interrupt_reason =
413 history::ToHistoryDownloadInterruptReason(interrupt_reason);
414 info->id = history::ToHistoryDownloadId(id);
415 info->opened = opened;
416 info->by_ext_id = by_extension_id;
417 info->by_ext_name = by_extension_name;
419 EXPECT_CALL(item(index), GetId()).WillRepeatedly(Return(id));
420 EXPECT_CALL(item(index), GetFullPath())
421 .WillRepeatedly(ReturnRefOfCopy(current_path));
422 EXPECT_CALL(item(index), GetTargetFilePath())
423 .WillRepeatedly(ReturnRefOfCopy(target_path));
424 DCHECK_LE(1u, url_chain.size());
425 EXPECT_CALL(item(index), GetURL())
426 .WillRepeatedly(ReturnRefOfCopy(url_chain[0]));
427 EXPECT_CALL(item(index), GetUrlChain())
428 .WillRepeatedly(ReturnRefOfCopy(url_chain));
429 EXPECT_CALL(item(index), GetMimeType()).WillRepeatedly(Return(mime_type));
430 EXPECT_CALL(item(index), GetOriginalMimeType()).WillRepeatedly(Return(
431 original_mime_type));
432 EXPECT_CALL(item(index), GetReferrerUrl())
433 .WillRepeatedly(ReturnRefOfCopy(referrer));
434 EXPECT_CALL(item(index), GetStartTime()).WillRepeatedly(Return(start_time));
435 EXPECT_CALL(item(index), GetEndTime()).WillRepeatedly(Return(end_time));
436 EXPECT_CALL(item(index), GetETag()).WillRepeatedly(ReturnRefOfCopy(etag));
437 EXPECT_CALL(item(index), GetLastModifiedTime())
438 .WillRepeatedly(ReturnRefOfCopy(last_modified));
439 EXPECT_CALL(item(index), GetReceivedBytes())
440 .WillRepeatedly(Return(received_bytes));
441 EXPECT_CALL(item(index), GetTotalBytes())
442 .WillRepeatedly(Return(total_bytes));
443 EXPECT_CALL(item(index), GetState()).WillRepeatedly(Return(state));
444 EXPECT_CALL(item(index), GetDangerType())
445 .WillRepeatedly(Return(danger_type));
446 EXPECT_CALL(item(index), GetLastReason())
447 .WillRepeatedly(Return(interrupt_reason));
448 EXPECT_CALL(item(index), GetOpened()).WillRepeatedly(Return(opened));
449 EXPECT_CALL(item(index), GetTargetDisposition())
450 .WillRepeatedly(
451 Return(content::DownloadItem::TARGET_DISPOSITION_OVERWRITE));
452 EXPECT_CALL(manager(), GetDownload(id))
453 .WillRepeatedly(Return(&item(index)));
454 EXPECT_CALL(item(index), IsTemporary()).WillRepeatedly(Return(false));
455 #if defined(ENABLE_EXTENSIONS)
456 new extensions::DownloadedByExtension(
457 &item(index), by_extension_id, by_extension_name);
458 #endif
460 std::vector<content::DownloadItem*> items;
461 for (size_t i = 0; i < items_.size(); ++i) {
462 items.push_back(&item(i));
464 EXPECT_CALL(*manager_.get(), GetAllDownloads(_))
465 .WillRepeatedly(SetArgPointee<0>(items));
468 private:
469 void CheckDownloadWasRestoredFromHistory(bool expected_value,
470 content::MockDownloadItem* item) {
471 ASSERT_TRUE(download_history_.get());
472 EXPECT_EQ(expected_value, download_history_->WasRestoredFromHistory(item));
475 base::MessageLoopForUI loop_;
476 content::TestBrowserThread ui_thread_;
477 std::vector<StrictMockDownloadItem*> items_;
478 scoped_ptr<content::MockDownloadManager> manager_;
479 FakeHistoryAdapter* history_;
480 scoped_ptr<DownloadHistory> download_history_;
481 content::DownloadManager::Observer* manager_observer_;
482 size_t download_created_index_;
483 DownloadItemCallback pre_on_create_handler_;
484 DownloadItemCallback post_on_create_handler_;
486 DISALLOW_COPY_AND_ASSIGN(DownloadHistoryTest);
489 // Test loading an item from the database, changing it, saving it back, removing
490 // it.
491 TEST_F(DownloadHistoryTest, DownloadHistoryTest_Load) {
492 // Load a download from history, create the item, OnDownloadCreated,
493 // OnDownloadUpdated, OnDownloadRemoved.
494 history::DownloadRow info;
495 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
496 "http://example.com/bar.pdf",
497 "http://example.com/referrer.html",
498 &info);
500 scoped_ptr<InfoVector> infos(new InfoVector());
501 infos->push_back(info);
502 CreateDownloadHistory(infos.Pass());
503 ExpectNoDownloadCreated();
505 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
507 // Pretend that something changed on the item.
508 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
509 item(0).NotifyObserversDownloadUpdated();
510 info.opened = true;
511 ExpectDownloadUpdated(info);
513 // Pretend that the user removed the item.
514 IdSet ids;
515 ids.insert(info.id);
516 item(0).NotifyObserversDownloadRemoved();
517 ExpectDownloadsRemoved(ids);
520 // Test that WasRestoredFromHistory accurately identifies downloads that were
521 // created from history, even during an OnDownloadCreated() handler.
522 TEST_F(DownloadHistoryTest, DownloadHistoryTest_WasRestoredFromHistory_True) {
523 // This sets DownloadHistoryTest to call DH::WasRestoredFromHistory() both
524 // before and after DH::OnDownloadCreated() is called. At each call, the
525 // expected return value is |true| since the download was restored from
526 // history.
527 ExpectDownloadsRestoredFromHistory(true);
529 // Construct a DownloadHistory with a single history download. This results in
530 // DownloadManager::CreateDownload() being called for the restored download.
531 // The above test expectation should verify that the value of
532 // WasRestoredFromHistory is correct for this download.
533 history::DownloadRow info;
534 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
535 "http://example.com/bar.pdf",
536 "http://example.com/referrer.html",
537 &info);
538 scoped_ptr<InfoVector> infos(new InfoVector());
539 infos->push_back(info);
540 CreateDownloadHistory(infos.Pass());
542 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
545 // Test that WasRestoredFromHistory accurately identifies downloads that were
546 // not created from history.
547 TEST_F(DownloadHistoryTest, DownloadHistoryTest_WasRestoredFromHistory_False) {
548 // This sets DownloadHistoryTest to call DH::WasRestoredFromHistory() both
549 // before and after DH::OnDownloadCreated() is called. At each call, the
550 // expected return value is |true| since the download was restored from
551 // history.
552 ExpectDownloadsRestoredFromHistory(false);
554 // Create a DownloadHistory with no history downloads. No
555 // DownloadManager::CreateDownload() calls are expected.
556 CreateDownloadHistory(scoped_ptr<InfoVector>(new InfoVector()));
558 // Notify DownloadHistory that a new download was created. The above test
559 // expecation should verify that WasRestoredFromHistory is correct for this
560 // download.
561 history::DownloadRow info;
562 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
563 "http://example.com/bar.pdf",
564 "http://example.com/referrer.html",
565 &info);
566 CallOnDownloadCreated(0);
567 ExpectDownloadCreated(info);
570 // Test creating an item, saving it to the database, changing it, saving it
571 // back, removing it.
572 TEST_F(DownloadHistoryTest, DownloadHistoryTest_Create) {
573 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
574 // OnDownloadRemoved.
575 CreateDownloadHistory(scoped_ptr<InfoVector>(new InfoVector()));
577 history::DownloadRow info;
578 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
579 "http://example.com/bar.pdf",
580 "http://example.com/referrer.html",
581 &info);
583 // Pretend the manager just created |item|.
584 CallOnDownloadCreated(0);
585 ExpectDownloadCreated(info);
586 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
588 // Pretend that something changed on the item.
589 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
590 item(0).NotifyObserversDownloadUpdated();
591 info.opened = true;
592 ExpectDownloadUpdated(info);
594 // Pretend that the user removed the item.
595 IdSet ids;
596 ids.insert(info.id);
597 item(0).NotifyObserversDownloadRemoved();
598 ExpectDownloadsRemoved(ids);
601 // Test that changes to persisted fields in a DownloadItem triggers database
602 // updates.
603 TEST_F(DownloadHistoryTest, DownloadHistoryTest_Update) {
604 CreateDownloadHistory(scoped_ptr<InfoVector>(new InfoVector()));
606 history::DownloadRow info;
607 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
608 "http://example.com/bar.pdf",
609 "http://example.com/referrer.html",
610 &info);
611 CallOnDownloadCreated(0);
612 ExpectDownloadCreated(info);
613 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
615 base::FilePath new_path(FILE_PATH_LITERAL("/foo/baz.txt"));
616 base::Time new_time(base::Time::Now());
617 std::string new_etag("new etag");
618 std::string new_last_modifed("new last modified");
620 // current_path
621 EXPECT_CALL(item(0), GetFullPath()).WillRepeatedly(ReturnRefOfCopy(new_path));
622 info.current_path = new_path;
623 item(0).NotifyObserversDownloadUpdated();
624 ExpectDownloadUpdated(info);
626 // target_path
627 EXPECT_CALL(item(0), GetTargetFilePath())
628 .WillRepeatedly(ReturnRefOfCopy(new_path));
629 info.target_path = new_path;
630 item(0).NotifyObserversDownloadUpdated();
631 ExpectDownloadUpdated(info);
633 // end_time
634 EXPECT_CALL(item(0), GetEndTime()).WillRepeatedly(Return(new_time));
635 info.end_time = new_time;
636 item(0).NotifyObserversDownloadUpdated();
637 ExpectDownloadUpdated(info);
639 // received_bytes
640 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(101));
641 info.received_bytes = 101;
642 item(0).NotifyObserversDownloadUpdated();
643 ExpectDownloadUpdated(info);
645 // total_bytes
646 EXPECT_CALL(item(0), GetTotalBytes()).WillRepeatedly(Return(102));
647 info.total_bytes = 102;
648 item(0).NotifyObserversDownloadUpdated();
649 ExpectDownloadUpdated(info);
651 // etag
652 EXPECT_CALL(item(0), GetETag()).WillRepeatedly(ReturnRefOfCopy(new_etag));
653 info.etag = new_etag;
654 item(0).NotifyObserversDownloadUpdated();
655 ExpectDownloadUpdated(info);
657 // last_modified
658 EXPECT_CALL(item(0), GetLastModifiedTime())
659 .WillRepeatedly(ReturnRefOfCopy(new_last_modifed));
660 info.last_modified = new_last_modifed;
661 item(0).NotifyObserversDownloadUpdated();
662 ExpectDownloadUpdated(info);
664 // state
665 EXPECT_CALL(item(0), GetState())
666 .WillRepeatedly(Return(content::DownloadItem::INTERRUPTED));
667 info.state = history::DownloadState::INTERRUPTED;
668 item(0).NotifyObserversDownloadUpdated();
669 ExpectDownloadUpdated(info);
671 // danger_type
672 EXPECT_CALL(item(0), GetDangerType())
673 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT));
674 info.danger_type = history::DownloadDangerType::DANGEROUS_CONTENT;
675 item(0).NotifyObserversDownloadUpdated();
676 ExpectDownloadUpdated(info);
678 // interrupt_reason
679 EXPECT_CALL(item(0), GetLastReason())
680 .WillRepeatedly(Return(content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED));
681 info.interrupt_reason = history::ToHistoryDownloadInterruptReason(
682 content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED);
683 item(0).NotifyObserversDownloadUpdated();
684 ExpectDownloadUpdated(info);
686 // opened
687 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
688 info.opened = true;
689 item(0).NotifyObserversDownloadUpdated();
690 ExpectDownloadUpdated(info);
693 // Test creating a new item, saving it, removing it by setting it Temporary,
694 // changing it without saving it back because it's Temporary, clearing
695 // IsTemporary, saving it back, changing it, saving it back because it isn't
696 // Temporary anymore.
697 TEST_F(DownloadHistoryTest, DownloadHistoryTest_Temporary) {
698 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
699 // OnDownloadRemoved.
700 CreateDownloadHistory(scoped_ptr<InfoVector>(new InfoVector()));
702 history::DownloadRow info;
703 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
704 "http://example.com/bar.pdf",
705 "http://example.com/referrer.html",
706 &info);
708 // Pretend the manager just created |item|.
709 CallOnDownloadCreated(0);
710 ExpectDownloadCreated(info);
711 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
713 // Pretend the item was marked temporary. DownloadHistory should remove it
714 // from history and start ignoring it.
715 EXPECT_CALL(item(0), IsTemporary()).WillRepeatedly(Return(true));
716 item(0).NotifyObserversDownloadUpdated();
717 IdSet ids;
718 ids.insert(info.id);
719 ExpectDownloadsRemoved(ids);
721 // Change something that would make DownloadHistory call UpdateDownload if the
722 // item weren't temporary.
723 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(4200));
724 item(0).NotifyObserversDownloadUpdated();
725 ExpectNoDownloadUpdated();
727 // Changing a temporary item back to a non-temporary item should make
728 // DownloadHistory call CreateDownload.
729 EXPECT_CALL(item(0), IsTemporary()).WillRepeatedly(Return(false));
730 item(0).NotifyObserversDownloadUpdated();
731 info.received_bytes = 4200;
732 ExpectDownloadCreated(info);
733 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
735 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(100));
736 item(0).NotifyObserversDownloadUpdated();
737 info.received_bytes = 100;
738 ExpectDownloadUpdated(info);
741 // Test removing downloads while they're still being added.
742 TEST_F(DownloadHistoryTest, DownloadHistoryTest_RemoveWhileAdding) {
743 CreateDownloadHistory(scoped_ptr<InfoVector>(new InfoVector()));
745 history::DownloadRow info;
746 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
747 "http://example.com/bar.pdf",
748 "http://example.com/referrer.html",
749 &info);
751 // Instruct CreateDownload() to not callback to DownloadHistory immediately,
752 // but to wait for FinishCreateDownload().
753 set_slow_create_download(true);
755 // Pretend the manager just created |item|.
756 CallOnDownloadCreated(0);
757 ExpectDownloadCreated(info);
758 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
760 // Call OnDownloadRemoved before calling back to DownloadHistory::ItemAdded().
761 // Instead of calling RemoveDownloads() immediately, DownloadHistory should
762 // add the item's id to removed_while_adding_. Then, ItemAdded should
763 // immediately remove the item's record from history.
764 item(0).NotifyObserversDownloadRemoved();
765 EXPECT_CALL(manager(), GetDownload(item(0).GetId()))
766 .WillRepeatedly(Return(static_cast<content::DownloadItem*>(NULL)));
767 ExpectNoDownloadsRemoved();
768 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
770 // Now callback to DownloadHistory::ItemAdded(), and expect a call to
771 // RemoveDownloads() for the item that was removed while it was being added.
772 FinishCreateDownload();
773 IdSet ids;
774 ids.insert(info.id);
775 ExpectDownloadsRemoved(ids);
776 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
779 // Test loading multiple items from the database and removing them all.
780 TEST_F(DownloadHistoryTest, DownloadHistoryTest_Multiple) {
781 // Load a download from history, create the item, OnDownloadCreated,
782 // OnDownloadUpdated, OnDownloadRemoved.
783 history::DownloadRow info0, info1;
784 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
785 "http://example.com/bar.pdf",
786 "http://example.com/referrer.html",
787 &info0);
788 InitBasicItem(FILE_PATH_LITERAL("/foo/qux.pdf"),
789 "http://example.com/qux.pdf",
790 "http://example.com/referrer1.html",
791 &info1);
793 scoped_ptr<InfoVector> infos(new InfoVector());
794 infos->push_back(info0);
795 infos->push_back(info1);
796 CreateDownloadHistory(infos.Pass());
797 ExpectNoDownloadCreated();
800 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
801 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(1)));
803 // Pretend that the user removed both items.
804 IdSet ids;
805 ids.insert(info0.id);
806 ids.insert(info1.id);
807 item(0).NotifyObserversDownloadRemoved();
808 item(1).NotifyObserversDownloadRemoved();
809 ExpectDownloadsRemoved(ids);
812 // Test what happens when HistoryService/CreateDownload::CreateDownload() fails.
813 TEST_F(DownloadHistoryTest, DownloadHistoryTest_CreateFailed) {
814 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
815 // OnDownloadRemoved.
816 CreateDownloadHistory(scoped_ptr<InfoVector>(new InfoVector()));
818 history::DownloadRow info;
819 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
820 "http://example.com/bar.pdf",
821 "http://example.com/referrer.html",
822 &info);
824 FailCreateDownload();
825 // Pretend the manager just created |item|.
826 CallOnDownloadCreated(0);
827 ExpectDownloadCreated(info);
828 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
830 EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(100));
831 item(0).NotifyObserversDownloadUpdated();
832 info.received_bytes = 100;
833 ExpectDownloadCreated(info);
834 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
837 TEST_F(DownloadHistoryTest, DownloadHistoryTest_UpdateWhileAdding) {
838 // Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
839 // OnDownloadRemoved.
840 CreateDownloadHistory(scoped_ptr<InfoVector>(new InfoVector()));
842 history::DownloadRow info;
843 InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
844 "http://example.com/bar.pdf",
845 "http://example.com/referrer.html",
846 &info);
848 // Instruct CreateDownload() to not callback to DownloadHistory immediately,
849 // but to wait for FinishCreateDownload().
850 set_slow_create_download(true);
852 // Pretend the manager just created |item|.
853 CallOnDownloadCreated(0);
854 ExpectDownloadCreated(info);
855 EXPECT_FALSE(DownloadHistory::IsPersisted(&item(0)));
857 // Pretend that something changed on the item.
858 EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
859 item(0).NotifyObserversDownloadUpdated();
861 FinishCreateDownload();
862 EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
864 // ItemAdded should call OnDownloadUpdated, which should detect that the item
865 // changed while it was being added and call UpdateDownload immediately.
866 info.opened = true;
867 ExpectDownloadUpdated(info);
870 } // anonymous namespace