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/bind.h" 6 #include "base/files/file_path.h" 7 #include "chrome/browser/download/download_danger_prompt.h" 8 #include "chrome/browser/ui/browser.h" 9 #include "chrome/browser/ui/browser_commands.h" 10 #include "chrome/browser/ui/browser_tabstrip.h" 11 #include "chrome/browser/ui/tabs/tab_strip_model.h" 12 #include "chrome/test/base/in_process_browser_test.h" 13 #include "chrome/test/base/ui_test_utils.h" 14 #include "content/public/test/mock_download_item.h" 15 #include "testing/gmock/include/gmock/gmock.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 using ::testing::_; 19 using ::testing::ByRef; 20 using ::testing::Eq; 21 using ::testing::Return; 22 using ::testing::SaveArg; 23 24 class DownloadDangerPromptTest : public InProcessBrowserTest { 25 public: 26 DownloadDangerPromptTest() 27 : download_observer_(NULL), 28 prompt_(NULL), 29 expected_action_(DownloadDangerPrompt::CANCEL), 30 did_receive_callback_(false) { 31 } 32 33 virtual ~DownloadDangerPromptTest() { 34 } 35 36 // Opens a new tab and waits for navigations to finish. If there are pending 37 // navigations, the constrained prompt might be dismissed when the navigation 38 // completes. 39 void OpenNewTab() { 40 ui_test_utils::NavigateToURLWithDisposition( 41 browser(), GURL("about:blank"), 42 NEW_FOREGROUND_TAB, 43 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB | 44 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 45 } 46 47 void SetUpExpectations(DownloadDangerPrompt::Action expected_action) { 48 did_receive_callback_ = false; 49 expected_action_ = expected_action; 50 SetUpDownloadItemExpectations(); 51 CreatePrompt(); 52 } 53 54 void VerifyExpectations() { 55 content::RunAllPendingInMessageLoop(); 56 // At the end of each test, we expect no more activity from the prompt. The 57 // prompt shouldn't exist anymore either. 58 EXPECT_TRUE(did_receive_callback_); 59 EXPECT_FALSE(prompt_); 60 testing::Mock::VerifyAndClearExpectations(&download_); 61 } 62 63 void SimulatePromptAction(DownloadDangerPrompt::Action action) { 64 prompt_->InvokeActionForTesting(action); 65 } 66 67 content::MockDownloadItem& download() { return download_; } 68 69 content::DownloadItem::Observer* download_observer() { 70 return download_observer_; 71 } 72 73 DownloadDangerPrompt* prompt() { return prompt_; } 74 75 private: 76 void SetUpDownloadItemExpectations() { 77 EXPECT_CALL(download_, GetFileNameToReportUser()).WillRepeatedly(Return( 78 base::FilePath(FILE_PATH_LITERAL("evil.exe")))); 79 EXPECT_CALL(download_, AddObserver(_)) 80 .WillOnce(SaveArg<0>(&download_observer_)); 81 EXPECT_CALL(download_, RemoveObserver(Eq(ByRef(download_observer_)))); 82 EXPECT_CALL(download_, GetDangerType()) 83 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL)); 84 } 85 86 void CreatePrompt() { 87 prompt_ = DownloadDangerPrompt::Create( 88 &download_, 89 browser()->tab_strip_model()->GetActiveWebContents(), 90 false, 91 base::Bind(&DownloadDangerPromptTest::PromptCallback, this)); 92 content::RunAllPendingInMessageLoop(); 93 } 94 95 void PromptCallback(DownloadDangerPrompt::Action action) { 96 EXPECT_FALSE(did_receive_callback_); 97 EXPECT_EQ(expected_action_, action); 98 did_receive_callback_ = true; 99 prompt_ = NULL; 100 } 101 102 content::MockDownloadItem download_; 103 content::DownloadItem::Observer* download_observer_; 104 DownloadDangerPrompt* prompt_; 105 DownloadDangerPrompt::Action expected_action_; 106 bool did_receive_callback_; 107 108 DISALLOW_COPY_AND_ASSIGN(DownloadDangerPromptTest); 109 }; 110 111 IN_PROC_BROWSER_TEST_F(DownloadDangerPromptTest, TestAll) { 112 OpenNewTab(); 113 114 // Clicking the Accept button should invoke the ACCEPT action. 115 SetUpExpectations(DownloadDangerPrompt::ACCEPT); 116 SimulatePromptAction(DownloadDangerPrompt::ACCEPT); 117 VerifyExpectations(); 118 119 // Clicking the Cancel button should invoke the CANCEL action. 120 SetUpExpectations(DownloadDangerPrompt::CANCEL); 121 SimulatePromptAction(DownloadDangerPrompt::CANCEL); 122 VerifyExpectations(); 123 124 // If the download is no longer dangerous (because it was accepted), the 125 // dialog should DISMISS itself. 126 SetUpExpectations(DownloadDangerPrompt::DISMISS); 127 EXPECT_CALL(download(), IsDangerous()).WillOnce(Return(false)); 128 download_observer()->OnDownloadUpdated(&download()); 129 VerifyExpectations(); 130 131 // If the download is in a terminal state then the dialog should DISMISS 132 // itself. 133 SetUpExpectations(DownloadDangerPrompt::DISMISS); 134 EXPECT_CALL(download(), IsDangerous()).WillOnce(Return(true)); 135 EXPECT_CALL(download(), IsDone()).WillOnce(Return(true)); 136 download_observer()->OnDownloadUpdated(&download()); 137 VerifyExpectations(); 138 139 // If the download is dangerous and is not in a terminal state, don't dismiss 140 // the dialog. 141 SetUpExpectations(DownloadDangerPrompt::ACCEPT); 142 EXPECT_CALL(download(), IsDangerous()).WillOnce(Return(true)); 143 EXPECT_CALL(download(), IsDone()).WillOnce(Return(false)); 144 download_observer()->OnDownloadUpdated(&download()); 145 SimulatePromptAction(DownloadDangerPrompt::ACCEPT); 146 VerifyExpectations(); 147 148 // If the containing tab is closed, the dialog should DISMISS itself. 149 OpenNewTab(); 150 SetUpExpectations(DownloadDangerPrompt::DISMISS); 151 chrome::CloseTab(browser()); 152 VerifyExpectations(); 153 } 154