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.
4
5#include "base/compiler_specific.h"
6#include "base/memory/scoped_ptr.h"
7#include "base/message_loop/message_loop.h"
8#include "base/run_loop.h"
9#include "chrome/browser/chrome_notification_types.h"
10#include "chrome/browser/download/download_item_model.h"
11#include "chrome/browser/download/download_service.h"
12#include "chrome/browser/download/download_service_factory.h"
13#include "chrome/browser/download/test_download_shelf.h"
14#include "chrome/test/base/testing_profile.h"
15#include "content/public/browser/notification_service.h"
16#include "content/public/test/mock_download_item.h"
17#include "content/public/test/mock_download_manager.h"
18#include "content/public/test/test_browser_thread.h"
19#include "extensions/common/extension.h"
20#include "testing/gmock/include/gmock/gmock.h"
21#include "testing/gtest/include/gtest/gtest.h"
22
23using ::testing::Return;
24using ::testing::ReturnRefOfCopy;
25using ::testing::SaveArg;
26using ::testing::_;
27using content::DownloadItem;
28
29namespace {
30
31KeyedService* CreateDownloadService(content::BrowserContext* context) {
32  return new DownloadService(Profile::FromBrowserContext(context));
33}
34
35class DownloadShelfTest : public testing::Test {
36 public:
37  DownloadShelfTest();
38
39 protected:
40  content::MockDownloadItem* download_item() {
41    return download_item_.get();
42  }
43  content::MockDownloadManager* download_manager() {
44    return download_manager_.get();
45  }
46  TestDownloadShelf* shelf() {
47    return &shelf_;
48  }
49  Profile* profile() { return profile_.get(); }
50
51  virtual void SetUp() OVERRIDE {
52    DownloadServiceFactory::GetInstance()->SetTestingFactory(
53        profile(), &CreateDownloadService);
54  }
55
56  virtual void TearDown() OVERRIDE {
57    DownloadServiceFactory::GetInstance()->SetTestingFactory(
58        profile(), NULL);
59  }
60
61 private:
62  scoped_ptr<content::MockDownloadItem> GetInProgressMockDownload();
63
64  base::MessageLoopForUI message_loop_;
65  content::TestBrowserThread ui_thread_;
66  scoped_ptr<content::MockDownloadItem> download_item_;
67  scoped_ptr<content::MockDownloadManager> download_manager_;
68  TestDownloadShelf shelf_;
69  scoped_ptr<TestingProfile> profile_;
70};
71
72DownloadShelfTest::DownloadShelfTest()
73    : ui_thread_(content::BrowserThread::UI, &message_loop_),
74      profile_(new TestingProfile()) {
75  download_item_.reset(new ::testing::NiceMock<content::MockDownloadItem>());
76  ON_CALL(*download_item_, GetAutoOpened()).WillByDefault(Return(false));
77  ON_CALL(*download_item_, GetMimeType()).WillByDefault(Return("text/plain"));
78  ON_CALL(*download_item_, GetOpenWhenComplete()).WillByDefault(Return(false));
79  ON_CALL(*download_item_, GetTargetDisposition())
80      .WillByDefault(Return(DownloadItem::TARGET_DISPOSITION_OVERWRITE));
81  ON_CALL(*download_item_, GetURL())
82      .WillByDefault(ReturnRefOfCopy(GURL("http://example.com/foo")));
83  ON_CALL(*download_item_, GetState())
84      .WillByDefault(Return(DownloadItem::IN_PROGRESS));
85  ON_CALL(*download_item_, IsTemporary()).WillByDefault(Return(false));
86  ON_CALL(*download_item_, ShouldOpenFileBasedOnExtension())
87      .WillByDefault(Return(false));
88  ON_CALL(*download_item_, GetBrowserContext())
89      .WillByDefault(Return(profile()));
90
91  download_manager_.reset(
92      new ::testing::NiceMock<content::MockDownloadManager>());
93  ON_CALL(*download_manager_, GetDownload(_))
94      .WillByDefault(Return(download_item_.get()));
95  ON_CALL(*download_manager_, GetBrowserContext())
96      .WillByDefault(Return(profile()));
97
98  shelf_.set_download_manager(download_manager_.get());
99}
100
101} // namespace
102
103TEST_F(DownloadShelfTest, ClosesShelfWhenHidden) {
104  shelf()->Show();
105  EXPECT_TRUE(shelf()->IsShowing());
106  shelf()->Hide();
107  EXPECT_FALSE(shelf()->IsShowing());
108  shelf()->Unhide();
109  EXPECT_TRUE(shelf()->IsShowing());
110}
111
112TEST_F(DownloadShelfTest, CloseWhileHiddenPreventsShowOnUnhide) {
113  shelf()->Show();
114  shelf()->Hide();
115  shelf()->Close(DownloadShelf::AUTOMATIC);
116  shelf()->Unhide();
117  EXPECT_FALSE(shelf()->IsShowing());
118}
119
120TEST_F(DownloadShelfTest, UnhideDoesntShowIfNotShownOnHide) {
121  shelf()->Hide();
122  shelf()->Unhide();
123  EXPECT_FALSE(shelf()->IsShowing());
124}
125
126TEST_F(DownloadShelfTest, AddDownloadWhileHiddenUnhides) {
127  shelf()->Show();
128  shelf()->Hide();
129  shelf()->AddDownload(download_item());
130  EXPECT_TRUE(shelf()->IsShowing());
131}
132
133TEST_F(DownloadShelfTest, AddDownloadWhileHiddenUnhidesAndShows) {
134  shelf()->Hide();
135  shelf()->AddDownload(download_item());
136  EXPECT_TRUE(shelf()->IsShowing());
137}
138
139// Normal downloads should be added synchronously and cause the shelf to show.
140TEST_F(DownloadShelfTest, AddNormalDownload) {
141  EXPECT_FALSE(shelf()->IsShowing());
142  shelf()->AddDownload(download_item());
143  EXPECT_TRUE(shelf()->did_add_download());
144  EXPECT_TRUE(shelf()->IsShowing());
145}
146
147// Add a transient download. It should not be added immediately. Instead it
148// should be added after a delay. For testing, the delay is set to 0 seconds. So
149// the download should be added once the message loop is flushed.
150TEST_F(DownloadShelfTest, AddDelayedDownload) {
151  EXPECT_CALL(*download_item(), ShouldOpenFileBasedOnExtension())
152      .WillRepeatedly(Return(true));
153  ASSERT_TRUE(DownloadItemModel(download_item())
154              .ShouldRemoveFromShelfWhenComplete());
155  shelf()->AddDownload(download_item());
156
157  EXPECT_FALSE(shelf()->did_add_download());
158  EXPECT_FALSE(shelf()->IsShowing());
159
160  base::RunLoop run_loop;
161  run_loop.RunUntilIdle();
162
163  EXPECT_TRUE(shelf()->did_add_download());
164  EXPECT_TRUE(shelf()->IsShowing());
165}
166
167// Add a transient download that completes before the delay. It should not be
168// displayed on the shelf.
169TEST_F(DownloadShelfTest, AddDelayedCompletedDownload) {
170  EXPECT_CALL(*download_item(), ShouldOpenFileBasedOnExtension())
171      .WillRepeatedly(Return(true));
172  ASSERT_TRUE(DownloadItemModel(download_item())
173              .ShouldRemoveFromShelfWhenComplete());
174  shelf()->AddDownload(download_item());
175
176  EXPECT_FALSE(shelf()->did_add_download());
177  EXPECT_FALSE(shelf()->IsShowing());
178
179  EXPECT_CALL(*download_item(), GetState())
180      .WillRepeatedly(Return(DownloadItem::COMPLETE));
181  EXPECT_CALL(*download_item(), GetAutoOpened())
182      .WillRepeatedly(Return(true));
183
184  base::RunLoop run_loop;
185  run_loop.RunUntilIdle();
186
187  EXPECT_FALSE(shelf()->did_add_download());
188  EXPECT_FALSE(shelf()->IsShowing());
189}
190
191// Add a transient download that completes and becomes non-transient before the
192// delay. It should be displayed on the shelf even though it is complete.
193TEST_F(DownloadShelfTest, AddDelayedCompleteNonTransientDownload) {
194  EXPECT_CALL(*download_item(), ShouldOpenFileBasedOnExtension())
195      .WillRepeatedly(Return(true));
196  ASSERT_TRUE(DownloadItemModel(download_item())
197              .ShouldRemoveFromShelfWhenComplete());
198  shelf()->AddDownload(download_item());
199
200  EXPECT_FALSE(shelf()->did_add_download());
201  EXPECT_FALSE(shelf()->IsShowing());
202
203  EXPECT_CALL(*download_item(), GetState())
204      .WillRepeatedly(Return(DownloadItem::COMPLETE));
205  EXPECT_CALL(*download_item(), ShouldOpenFileBasedOnExtension())
206      .WillRepeatedly(Return(false));
207  ASSERT_FALSE(DownloadItemModel(download_item())
208               .ShouldRemoveFromShelfWhenComplete());
209
210  base::RunLoop run_loop;
211  run_loop.RunUntilIdle();
212
213  EXPECT_TRUE(shelf()->did_add_download());
214  EXPECT_TRUE(shelf()->IsShowing());
215}
216