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