blob: 6109c7f1f54937978c254a446714112d9135bdcb [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/download/download_item_warning_data.h"
#include <vector>
#include "base/test/task_environment.h"
#include "components/download/public/common/mock_download_item.h"
#include "testing/gtest/include/gtest/gtest.h"
using WarningSurface = DownloadItemWarningData::WarningSurface;
using WarningAction = DownloadItemWarningData::WarningAction;
using WarningActionEvent = DownloadItemWarningData::WarningActionEvent;
using DeepScanTrigger = DownloadItemWarningData::DeepScanTrigger;
using ::testing::Return;
class DownloadItemWarningDataTest : public testing::Test {
public:
DownloadItemWarningDataTest() {
ON_CALL(download_, IsDangerous()).WillByDefault(Return(true));
}
protected:
void FastForwardAndAddEvent(base::TimeDelta time_delta,
WarningSurface surface,
WarningAction action) {
task_environment_.FastForwardBy(time_delta);
DownloadItemWarningData::AddWarningActionEvent(&download_, surface, action);
}
std::vector<WarningActionEvent> GetEvents() {
return DownloadItemWarningData::GetWarningActionEvents(&download_);
}
bool VerifyEventValue(const WarningActionEvent& actual_event,
WarningSurface expected_surface,
WarningAction expected_action,
int64_t expected_latency,
bool expected_is_terminal_action) {
bool success = true;
if (actual_event.surface != expected_surface) {
success = false;
ADD_FAILURE() << "Warning action event should have surface "
<< static_cast<int>(expected_surface) << ", but found "
<< static_cast<int>(actual_event.surface);
}
if (actual_event.action != expected_action) {
success = false;
ADD_FAILURE() << "Warning action event should have action "
<< static_cast<int>(expected_action) << ", but found "
<< static_cast<int>(actual_event.action);
}
if (actual_event.action_latency_msec != expected_latency) {
success = false;
ADD_FAILURE() << "Warning action event should have latency "
<< expected_latency << ", but found "
<< actual_event.action_latency_msec;
}
if (actual_event.is_terminal_action != expected_is_terminal_action) {
success = false;
ADD_FAILURE() << "Warning action event should have is_terminal_action "
<< expected_is_terminal_action << ", but found "
<< actual_event.is_terminal_action;
}
return success;
}
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
download::MockDownloadItem download_;
};
TEST_F(DownloadItemWarningDataTest, GetEvents) {
FastForwardAndAddEvent(base::Seconds(0), WarningSurface::BUBBLE_MAINPAGE,
WarningAction::SHOWN);
FastForwardAndAddEvent(base::Seconds(5), WarningSurface::BUBBLE_SUBPAGE,
WarningAction::CLOSE);
FastForwardAndAddEvent(base::Seconds(10), WarningSurface::DOWNLOAD_PROMPT,
WarningAction::CANCEL);
FastForwardAndAddEvent(base::Seconds(15), WarningSurface::DOWNLOADS_PAGE,
WarningAction::DISCARD);
std::vector<WarningActionEvent> events = GetEvents();
ASSERT_EQ(3u, events.size());
EXPECT_TRUE(VerifyEventValue(events[0], WarningSurface::BUBBLE_SUBPAGE,
WarningAction::CLOSE, /*expected_latency=*/5000,
/*expected_is_terminal_action=*/false));
EXPECT_TRUE(VerifyEventValue(
events[1], WarningSurface::DOWNLOAD_PROMPT, WarningAction::CANCEL,
/*expected_latency=*/15000, /*expected_is_terminal_action=*/false));
EXPECT_TRUE(VerifyEventValue(
events[2], WarningSurface::DOWNLOADS_PAGE, WarningAction::DISCARD,
/*expected_latency=*/30000, /*expected_is_terminal_action=*/true));
}
TEST_F(DownloadItemWarningDataTest, GetEvents_Notification) {
FastForwardAndAddEvent(base::Seconds(0),
WarningSurface::DOWNLOAD_NOTIFICATION,
WarningAction::SHOWN);
FastForwardAndAddEvent(base::Seconds(5),
WarningSurface::DOWNLOAD_NOTIFICATION,
WarningAction::OPEN_SUBPAGE);
std::vector<WarningActionEvent> events = GetEvents();
ASSERT_EQ(1u, events.size());
EXPECT_TRUE(VerifyEventValue(events[0], WarningSurface::DOWNLOAD_NOTIFICATION,
WarningAction::OPEN_SUBPAGE,
/*expected_latency=*/5000,
/*expected_is_terminal_action=*/false));
}
TEST_F(DownloadItemWarningDataTest, GetEvents_WarningShownNotLogged) {
FastForwardAndAddEvent(base::Seconds(5), WarningSurface::BUBBLE_SUBPAGE,
WarningAction::PROCEED);
std::vector<WarningActionEvent> events = GetEvents();
// The events are not logged because the SHOWN event is not logged, so there
// is no anchor event to calculate the latency.
EXPECT_EQ(0u, events.size());
}
TEST_F(DownloadItemWarningDataTest, GetEvents_NotDangerous) {
ON_CALL(download_, IsDangerous()).WillByDefault(Return(false));
FastForwardAndAddEvent(base::Seconds(0), WarningSurface::BUBBLE_MAINPAGE,
WarningAction::SHOWN);
FastForwardAndAddEvent(base::Seconds(5), WarningSurface::BUBBLE_SUBPAGE,
WarningAction::PROCEED);
std::vector<WarningActionEvent> events = GetEvents();
// The events are not logged because download is not dangerous.
EXPECT_EQ(0u, events.size());
}
TEST_F(DownloadItemWarningDataTest, GetEvents_MultipleWarningShownLogged) {
FastForwardAndAddEvent(base::Seconds(0), WarningSurface::BUBBLE_MAINPAGE,
WarningAction::SHOWN);
FastForwardAndAddEvent(base::Seconds(5), WarningSurface::BUBBLE_MAINPAGE,
WarningAction::SHOWN);
FastForwardAndAddEvent(base::Seconds(5),
WarningSurface::DOWNLOAD_NOTIFICATION,
WarningAction::SHOWN);
FastForwardAndAddEvent(base::Seconds(5), WarningSurface::BUBBLE_SUBPAGE,
WarningAction::DISCARD);
std::vector<WarningActionEvent> events = GetEvents();
ASSERT_EQ(1u, events.size());
// The expected latency should be 15000 instead of 5000 because the latency
// should be anchored to the first shown event.
EXPECT_TRUE(VerifyEventValue(events[0], WarningSurface::BUBBLE_SUBPAGE,
WarningAction::DISCARD,
/*expected_latency=*/15000,
/*expected_is_terminal_action=*/true));
}
TEST_F(DownloadItemWarningDataTest, GetEvents_ExceedEventMaxLength) {
FastForwardAndAddEvent(base::Seconds(0), WarningSurface::BUBBLE_MAINPAGE,
WarningAction::SHOWN);
for (int i = 0; i <= 30; i++) {
FastForwardAndAddEvent(base::Seconds(5), WarningSurface::BUBBLE_SUBPAGE,
WarningAction::CLOSE);
}
std::vector<WarningActionEvent> events = GetEvents();
ASSERT_EQ(20u, events.size());
// The newer events should be ignored, so the expected latency of the last
// event should be the 20th event.
EXPECT_TRUE(VerifyEventValue(events[19], WarningSurface::BUBBLE_SUBPAGE,
WarningAction::CLOSE,
/*expected_latency=*/20 * 5000,
/*expected_is_terminal_action=*/false));
}
TEST_F(DownloadItemWarningDataTest, IsEncryptedArchive) {
EXPECT_FALSE(DownloadItemWarningData::IsTopLevelEncryptedArchive(&download_));
DownloadItemWarningData::SetIsTopLevelEncryptedArchive(&download_, true);
EXPECT_TRUE(DownloadItemWarningData::IsTopLevelEncryptedArchive(&download_));
}
TEST_F(DownloadItemWarningDataTest, HasIncorrectPassword) {
EXPECT_FALSE(DownloadItemWarningData::HasIncorrectPassword(&download_));
DownloadItemWarningData::SetHasIncorrectPassword(&download_, true);
EXPECT_TRUE(DownloadItemWarningData::HasIncorrectPassword(&download_));
}
TEST_F(DownloadItemWarningDataTest, HasShownLocalDecryptionPrompt) {
EXPECT_FALSE(
DownloadItemWarningData::HasShownLocalDecryptionPrompt(&download_));
DownloadItemWarningData::SetHasShownLocalDecryptionPrompt(&download_, true);
EXPECT_TRUE(
DownloadItemWarningData::HasShownLocalDecryptionPrompt(&download_));
}
TEST_F(DownloadItemWarningDataTest, DeepScanTrigger) {
EXPECT_EQ(DownloadItemWarningData::DownloadDeepScanTrigger(&download_),
DeepScanTrigger::TRIGGER_UNKNOWN);
DownloadItemWarningData::SetDeepScanTrigger(
&download_, DeepScanTrigger::TRIGGER_CONSUMER_PROMPT);
EXPECT_EQ(DownloadItemWarningData::DownloadDeepScanTrigger(&download_),
DeepScanTrigger::TRIGGER_CONSUMER_PROMPT);
}
TEST_F(DownloadItemWarningDataTest, FirstShownTimeAndSurface) {
EXPECT_EQ(DownloadItemWarningData::WarningFirstShownSurface(&download_),
std::nullopt);
EXPECT_TRUE(
DownloadItemWarningData::WarningFirstShownTime(&download_).is_null());
base::Time now = base::Time::Now();
FastForwardAndAddEvent(base::Seconds(0),
WarningSurface::DOWNLOAD_NOTIFICATION,
WarningAction::SHOWN);
FastForwardAndAddEvent(base::Seconds(5), WarningSurface::BUBBLE_MAINPAGE,
WarningAction::SHOWN);
EXPECT_EQ(*DownloadItemWarningData::WarningFirstShownSurface(&download_),
WarningSurface::DOWNLOAD_NOTIFICATION);
EXPECT_EQ(DownloadItemWarningData::WarningFirstShownTime(&download_), now);
}
TEST_F(DownloadItemWarningDataTest, EventToString) {
FastForwardAndAddEvent(base::Seconds(0), WarningSurface::BUBBLE_MAINPAGE,
WarningAction::SHOWN);
FastForwardAndAddEvent(base::Seconds(5), WarningSurface::BUBBLE_SUBPAGE,
WarningAction::CLOSE);
FastForwardAndAddEvent(base::Seconds(10), WarningSurface::DOWNLOAD_PROMPT,
WarningAction::CANCEL);
FastForwardAndAddEvent(base::Seconds(15), WarningSurface::DOWNLOADS_PAGE,
WarningAction::DISCARD);
std::vector<WarningActionEvent> events = GetEvents();
// The initial SHOWN event is not included.
EXPECT_EQ(events[0].ToString(), "BUBBLE_SUBPAGE:CLOSE:5000");
EXPECT_EQ(events[1].ToString(), "DOWNLOAD_PROMPT:CANCEL:15000");
EXPECT_EQ(events[2].ToString(), "DOWNLOADS_PAGE:DISCARD:30000");
}