blob: 6784e759c5eafef551e9747c5ec2d5469d4f7c07 [file] [log] [blame]
// Copyright 2017 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/permissions/crowd_deny_safe_browsing_request.h"
#include "base/memory/scoped_refptr.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "chrome/browser/permissions/crowd_deny_fake_safe_browsing_database_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace {
constexpr char kTestOriginFoo[] = "https://foo.com";
constexpr char kTestOriginBar[] = "https://bar.com";
} // namespace
class CrowdDenySafeBrowsingRequestTest : public testing::Test {
public:
using Verdict = CrowdDenySafeBrowsingRequest::Verdict;
CrowdDenySafeBrowsingRequestTest()
: fake_database_manager_(
base::MakeRefCounted<CrowdDenyFakeSafeBrowsingDatabaseManager>()) {}
CrowdDenySafeBrowsingRequestTest(const CrowdDenySafeBrowsingRequestTest&) =
delete;
CrowdDenySafeBrowsingRequestTest& operator=(
const CrowdDenySafeBrowsingRequestTest&) = delete;
~CrowdDenySafeBrowsingRequestTest() override = default;
protected:
content::BrowserTaskEnvironment* task_environment() {
return &task_environment_;
}
CrowdDenyFakeSafeBrowsingDatabaseManager* fake_database_manager() {
return fake_database_manager_.get();
}
const base::Clock* test_clock() { return task_environment_.GetMockClock(); }
void StartRequestForOriginAndExpectVerdict(const url::Origin& origin,
Verdict expected_verdict) {
base::HistogramTester histogram_tester;
base::MockOnceCallback<void(Verdict)> mock_callback_receiver;
CrowdDenySafeBrowsingRequest request(fake_database_manager(), test_clock(),
origin, mock_callback_receiver.Get());
EXPECT_CALL(mock_callback_receiver, Run(expected_verdict));
task_environment()->RunUntilIdle();
histogram_tester.ExpectTotalCount(
"Permissions.CrowdDeny.SafeBrowsing.RequestDuration", 1);
histogram_tester.ExpectUniqueSample(
"Permissions.CrowdDeny.SafeBrowsing.Verdict",
static_cast<int>(expected_verdict), 1);
}
private:
content::BrowserTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
scoped_refptr<CrowdDenyFakeSafeBrowsingDatabaseManager>
fake_database_manager_;
};
TEST_F(CrowdDenySafeBrowsingRequestTest, Acceptable_SynchronousCompletion) {
fake_database_manager()->set_simulate_synchronous_result(true);
StartRequestForOriginAndExpectVerdict(
url::Origin::Create(GURL(kTestOriginFoo)), Verdict::kAcceptable);
}
TEST_F(CrowdDenySafeBrowsingRequestTest, Acceptable_UnavailableMetaData) {
StartRequestForOriginAndExpectVerdict(
url::Origin::Create(GURL(kTestOriginFoo)), Verdict::kAcceptable);
}
TEST_F(CrowdDenySafeBrowsingRequestTest, Acceptable_UnknownAPIName) {
const GURL kTestURL(kTestOriginFoo);
safe_browsing::ThreatMetadata test_metadata;
test_metadata.api_permissions.emplace("");
test_metadata.api_permissions.emplace("Stuff");
test_metadata.api_permissions.emplace("NOTIFICATION"); // Singular.
test_metadata.api_permissions.emplace("notifications"); // Lowercase.
fake_database_manager()->SetSimulatedMetadataForUrl(kTestURL, test_metadata);
StartRequestForOriginAndExpectVerdict(url::Origin::Create(kTestURL),
Verdict::kAcceptable);
}
TEST_F(CrowdDenySafeBrowsingRequestTest, Spammy) {
const GURL kTestURL(kTestOriginFoo);
safe_browsing::ThreatMetadata test_metadata;
test_metadata.api_permissions.emplace("BANANAS");
test_metadata.api_permissions.emplace("NOTIFICATIONS");
test_metadata.api_permissions.emplace("ORANGES");
fake_database_manager()->SetSimulatedMetadataForUrl(kTestURL, test_metadata);
StartRequestForOriginAndExpectVerdict(url::Origin::Create(kTestURL),
Verdict::kUnacceptable);
StartRequestForOriginAndExpectVerdict(
url::Origin::Create(GURL(kTestOriginBar)), Verdict::kAcceptable);
}
TEST_F(CrowdDenySafeBrowsingRequestTest, Timeout) {
fake_database_manager()->set_simulate_timeout(true);
base::HistogramTester histogram_tester;
base::MockOnceCallback<void(Verdict)> mock_callback_receiver;
CrowdDenySafeBrowsingRequest request(
fake_database_manager(), test_clock(),
url::Origin::Create(GURL(kTestOriginFoo)), mock_callback_receiver.Get());
// Verify the request doesn't time out unreasonably fast.
EXPECT_CALL(mock_callback_receiver, Run(testing::_)).Times(0);
task_environment()->FastForwardBy(base::Milliseconds(100));
testing::Mock::VerifyAndClearExpectations(&mock_callback_receiver);
// But that it eventually does.
EXPECT_CALL(mock_callback_receiver, Run(Verdict::kAcceptable));
task_environment()->FastForwardUntilNoTasksRemain();
histogram_tester.ExpectUniqueSample(
"Permissions.CrowdDeny.SafeBrowsing.RequestDuration", 2000, 1);
histogram_tester.ExpectUniqueSample(
"Permissions.CrowdDeny.SafeBrowsing.Verdict",
static_cast<int>(Verdict::kAcceptable), 1);
}
TEST_F(CrowdDenySafeBrowsingRequestTest, AbandonedImmediately) {
fake_database_manager()->set_simulate_synchronous_result(true);
base::HistogramTester histogram_tester;
base::MockOnceCallback<void(Verdict)> mock_callback_receiver;
EXPECT_CALL(mock_callback_receiver, Run(testing::_)).Times(0);
{
CrowdDenySafeBrowsingRequest request(
fake_database_manager(), test_clock(),
url::Origin::Create(GURL(kTestOriginFoo)),
mock_callback_receiver.Get());
}
task_environment()->RunUntilIdle();
EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix("Permissions."),
testing::IsEmpty());
}
TEST_F(CrowdDenySafeBrowsingRequestTest, AbandonedWhileCheckPending) {
fake_database_manager()->set_simulate_timeout(true);
base::HistogramTester histogram_tester;
base::MockOnceCallback<void(Verdict)> mock_callback_receiver;
EXPECT_CALL(mock_callback_receiver, Run(testing::_)).Times(0);
CrowdDenySafeBrowsingRequest request(
fake_database_manager(), test_clock(),
url::Origin::Create(GURL(kTestOriginFoo)), mock_callback_receiver.Get());
task_environment()->FastForwardBy(base::Milliseconds(100));
EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix("Permissions."),
testing::IsEmpty());
}