// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_service.h" #include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/download/test_download_shelf.h" #include "chrome/test/base/testing_profile.h" #include "content/public/browser/notification_service.h" #include "content/public/test/mock_download_item.h" #include "content/public/test/mock_download_manager.h" #include "content/public/test/test_browser_thread.h" #include "extensions/common/extension.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using ::testing::Return; using ::testing::ReturnRefOfCopy; using ::testing::SaveArg; using ::testing::_; using content::DownloadItem; namespace { BrowserContextKeyedService* CreateDownloadService( content::BrowserContext* context) { return new DownloadService(Profile::FromBrowserContext(context)); } class DownloadShelfTest : public testing::Test { public: DownloadShelfTest(); protected: content::MockDownloadItem* download_item() { return download_item_.get(); } content::MockDownloadManager* download_manager() { return download_manager_.get(); } TestDownloadShelf* shelf() { return &shelf_; } Profile* profile() { return profile_.get(); } virtual void SetUp() OVERRIDE { DownloadServiceFactory::GetInstance()->SetTestingFactory( profile(), &CreateDownloadService); } virtual void TearDown() OVERRIDE { DownloadServiceFactory::GetInstance()->SetTestingFactory( profile(), NULL); } private: scoped_ptr<content::MockDownloadItem> GetInProgressMockDownload(); base::MessageLoopForUI message_loop_; content::TestBrowserThread ui_thread_; scoped_ptr<content::MockDownloadItem> download_item_; scoped_ptr<content::MockDownloadManager> download_manager_; TestDownloadShelf shelf_; scoped_ptr<TestingProfile> profile_; }; DownloadShelfTest::DownloadShelfTest() : ui_thread_(content::BrowserThread::UI, &message_loop_), profile_(new TestingProfile()) { download_item_.reset(new ::testing::NiceMock<content::MockDownloadItem>()); ON_CALL(*download_item_, GetAutoOpened()).WillByDefault(Return(false)); ON_CALL(*download_item_, GetMimeType()).WillByDefault(Return("text/plain")); ON_CALL(*download_item_, GetOpenWhenComplete()).WillByDefault(Return(false)); ON_CALL(*download_item_, GetTargetDisposition()) .WillByDefault(Return(DownloadItem::TARGET_DISPOSITION_OVERWRITE)); ON_CALL(*download_item_, GetURL()) .WillByDefault(ReturnRefOfCopy(GURL("http://example.com/foo"))); ON_CALL(*download_item_, GetState()) .WillByDefault(Return(DownloadItem::IN_PROGRESS)); ON_CALL(*download_item_, IsTemporary()).WillByDefault(Return(false)); ON_CALL(*download_item_, ShouldOpenFileBasedOnExtension()) .WillByDefault(Return(false)); ON_CALL(*download_item_, GetBrowserContext()) .WillByDefault(Return(profile())); download_manager_.reset( new ::testing::NiceMock<content::MockDownloadManager>()); ON_CALL(*download_manager_, GetDownload(_)) .WillByDefault(Return(download_item_.get())); ON_CALL(*download_manager_, GetBrowserContext()) .WillByDefault(Return(profile())); shelf_.set_download_manager(download_manager_.get()); } } // namespace TEST_F(DownloadShelfTest, ClosesShelfWhenHidden) { shelf()->Show(); EXPECT_TRUE(shelf()->IsShowing()); shelf()->Hide(); EXPECT_FALSE(shelf()->IsShowing()); shelf()->Unhide(); EXPECT_TRUE(shelf()->IsShowing()); } TEST_F(DownloadShelfTest, CloseWhileHiddenPreventsShowOnUnhide) { shelf()->Show(); shelf()->Hide(); shelf()->Close(DownloadShelf::AUTOMATIC); shelf()->Unhide(); EXPECT_FALSE(shelf()->IsShowing()); } TEST_F(DownloadShelfTest, UnhideDoesntShowIfNotShownOnHide) { shelf()->Hide(); shelf()->Unhide(); EXPECT_FALSE(shelf()->IsShowing()); } TEST_F(DownloadShelfTest, AddDownloadWhileHiddenUnhides) { shelf()->Show(); shelf()->Hide(); shelf()->AddDownload(download_item()); EXPECT_TRUE(shelf()->IsShowing()); } TEST_F(DownloadShelfTest, AddDownloadWhileHiddenUnhidesAndShows) { shelf()->Hide(); shelf()->AddDownload(download_item()); EXPECT_TRUE(shelf()->IsShowing()); } // Normal downloads should be added synchronously and cause the shelf to show. TEST_F(DownloadShelfTest, AddNormalDownload) { EXPECT_FALSE(shelf()->IsShowing()); shelf()->AddDownload(download_item()); EXPECT_TRUE(shelf()->did_add_download()); EXPECT_TRUE(shelf()->IsShowing()); } // Add a transient download. It should not be added immediately. Instead it // should be added after a delay. For testing, the delay is set to 0 seconds. So // the download should be added once the message loop is flushed. TEST_F(DownloadShelfTest, AddDelayedDownload) { EXPECT_CALL(*download_item(), ShouldOpenFileBasedOnExtension()) .WillRepeatedly(Return(true)); ASSERT_TRUE(DownloadItemModel(download_item()) .ShouldRemoveFromShelfWhenComplete()); shelf()->AddDownload(download_item()); EXPECT_FALSE(shelf()->did_add_download()); EXPECT_FALSE(shelf()->IsShowing()); base::RunLoop run_loop; run_loop.RunUntilIdle(); EXPECT_TRUE(shelf()->did_add_download()); EXPECT_TRUE(shelf()->IsShowing()); } // Add a transient download that completes before the delay. It should not be // displayed on the shelf. TEST_F(DownloadShelfTest, AddDelayedCompletedDownload) { EXPECT_CALL(*download_item(), ShouldOpenFileBasedOnExtension()) .WillRepeatedly(Return(true)); ASSERT_TRUE(DownloadItemModel(download_item()) .ShouldRemoveFromShelfWhenComplete()); shelf()->AddDownload(download_item()); EXPECT_FALSE(shelf()->did_add_download()); EXPECT_FALSE(shelf()->IsShowing()); EXPECT_CALL(*download_item(), GetState()) .WillRepeatedly(Return(DownloadItem::COMPLETE)); EXPECT_CALL(*download_item(), GetAutoOpened()) .WillRepeatedly(Return(true)); base::RunLoop run_loop; run_loop.RunUntilIdle(); EXPECT_FALSE(shelf()->did_add_download()); EXPECT_FALSE(shelf()->IsShowing()); } // Add a transient download that completes and becomes non-transient before the // delay. It should be displayed on the shelf even though it is complete. TEST_F(DownloadShelfTest, AddDelayedCompleteNonTransientDownload) { EXPECT_CALL(*download_item(), ShouldOpenFileBasedOnExtension()) .WillRepeatedly(Return(true)); ASSERT_TRUE(DownloadItemModel(download_item()) .ShouldRemoveFromShelfWhenComplete()); shelf()->AddDownload(download_item()); EXPECT_FALSE(shelf()->did_add_download()); EXPECT_FALSE(shelf()->IsShowing()); EXPECT_CALL(*download_item(), GetState()) .WillRepeatedly(Return(DownloadItem::COMPLETE)); EXPECT_CALL(*download_item(), ShouldOpenFileBasedOnExtension()) .WillRepeatedly(Return(false)); ASSERT_FALSE(DownloadItemModel(download_item()) .ShouldRemoveFromShelfWhenComplete()); base::RunLoop run_loop; run_loop.RunUntilIdle(); EXPECT_TRUE(shelf()->did_add_download()); EXPECT_TRUE(shelf()->IsShowing()); }