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 18using ::testing::_; 19using ::testing::ByRef; 20using ::testing::Eq; 21using ::testing::Return; 22using ::testing::SaveArg; 23 24class 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 } 83 84 void CreatePrompt() { 85 prompt_ = DownloadDangerPrompt::Create( 86 &download_, 87 browser()->tab_strip_model()->GetActiveWebContents(), 88 false, 89 base::Bind(&DownloadDangerPromptTest::PromptCallback, this)); 90 content::RunAllPendingInMessageLoop(); 91 } 92 93 void PromptCallback(DownloadDangerPrompt::Action action) { 94 EXPECT_FALSE(did_receive_callback_); 95 EXPECT_EQ(expected_action_, action); 96 did_receive_callback_ = true; 97 prompt_ = NULL; 98 } 99 100 content::MockDownloadItem download_; 101 content::DownloadItem::Observer* download_observer_; 102 DownloadDangerPrompt* prompt_; 103 DownloadDangerPrompt::Action expected_action_; 104 bool did_receive_callback_; 105 106 DISALLOW_COPY_AND_ASSIGN(DownloadDangerPromptTest); 107}; 108 109IN_PROC_BROWSER_TEST_F(DownloadDangerPromptTest, TestAll) { 110 OpenNewTab(); 111 112 // Clicking the Accept button should invoke the ACCEPT action. 113 SetUpExpectations(DownloadDangerPrompt::ACCEPT); 114 SimulatePromptAction(DownloadDangerPrompt::ACCEPT); 115 VerifyExpectations(); 116 117 // Clicking the Cancel button should invoke the CANCEL action. 118 SetUpExpectations(DownloadDangerPrompt::CANCEL); 119 SimulatePromptAction(DownloadDangerPrompt::CANCEL); 120 VerifyExpectations(); 121 122 // If the download is no longer dangerous (because it was accepted), the 123 // dialog should DISMISS itself. 124 SetUpExpectations(DownloadDangerPrompt::DISMISS); 125 EXPECT_CALL(download(), IsDangerous()).WillOnce(Return(false)); 126 download_observer()->OnDownloadUpdated(&download()); 127 VerifyExpectations(); 128 129 // If the download is in a terminal state then the dialog should DISMISS 130 // itself. 131 SetUpExpectations(DownloadDangerPrompt::DISMISS); 132 EXPECT_CALL(download(), IsDangerous()).WillOnce(Return(true)); 133 EXPECT_CALL(download(), IsDone()).WillOnce(Return(true)); 134 download_observer()->OnDownloadUpdated(&download()); 135 VerifyExpectations(); 136 137 // If the download is dangerous and is not in a terminal state, don't dismiss 138 // the dialog. 139 SetUpExpectations(DownloadDangerPrompt::ACCEPT); 140 EXPECT_CALL(download(), IsDangerous()).WillOnce(Return(true)); 141 EXPECT_CALL(download(), IsDone()).WillOnce(Return(false)); 142 download_observer()->OnDownloadUpdated(&download()); 143 SimulatePromptAction(DownloadDangerPrompt::ACCEPT); 144 VerifyExpectations(); 145 146 // If the containing tab is closed, the dialog should DISMISS itself. 147 OpenNewTab(); 148 // TODO(benjhayden): 149 // SetUpExpectations(DownloadDangerPrompt::DISMISS); 150 SetUpExpectations(DownloadDangerPrompt::CANCEL); 151 chrome::CloseTab(browser()); 152 VerifyExpectations(); 153} 154