blob: 5d7dff995352b99d89000f77f26116d459332216 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.h"
#include <map>
#include <vector>
#include "base/bind.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/safe_browsing/cloud_content_scanning/fake_deep_scanning_dialog_delegate.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_service.h"
#include "components/safe_browsing/common/safe_browsing_prefs.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace safe_browsing {
namespace {
const char kDmToken[] = "dm_token";
const char kTestUrl[] = "http://example.com";
class BaseTest : public testing::Test {
public:
BaseTest() : profile_manager_(TestingBrowserProcess::GetGlobal()) {
EXPECT_TRUE(profile_manager_.SetUp());
profile_ = profile_manager_.CreateTestingProfile("test-user");
}
void SetDMToken(const char* dm_token) {
DeepScanningDialogDelegate::SetDMTokenForTesting(dm_token);
}
void EnableFeatures(const std::vector<base::Feature>& features) {
scoped_feature_list_.Reset();
scoped_feature_list_.InitWithFeatures(features,
std::vector<base::Feature>());
}
void SetDlpPolicy(CheckContentComplianceValues state) {
TestingBrowserProcess::GetGlobal()->local_state()->SetInteger(
prefs::kCheckContentCompliance, state);
}
void SetWaitPolicy(DelayDeliveryUntilVerdictValues state) {
TestingBrowserProcess::GetGlobal()->local_state()->SetInteger(
prefs::kDelayDeliveryUntilVerdict, state);
}
void SetMalwarePolicy(SendFilesForMalwareCheckValues state) {
profile_->GetPrefs()->SetInteger(
prefs::kSafeBrowsingSendFilesForMalwareCheck, state);
}
void AddUrlToList(const char* pref_name, const GURL& url) {
ListPrefUpdate updater(TestingBrowserProcess::GetGlobal()->local_state(),
pref_name);
updater->GetList().emplace_back(url.host());
}
Profile* profile() { return profile_; }
private:
content::BrowserTaskEnvironment task_environment_;
base::test::ScopedFeatureList scoped_feature_list_;
TestingPrefServiceSimple pref_service_;
TestingProfileManager profile_manager_;
TestingProfile* profile_;
};
using DeepScanningDialogDelegateIsEnabledTest = BaseTest;
TEST_F(DeepScanningDialogDelegateIsEnabledTest, NoFeatureNoDMTokenNoPref) {
DeepScanningDialogDelegate::Data data;
EXPECT_FALSE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, NoDMTokenNoPref) {
EnableFeatures({kDeepScanningOfUploads});
DeepScanningDialogDelegate::Data data;
EXPECT_FALSE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, DlpNoPref) {
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
DeepScanningDialogDelegate::Data data;
EXPECT_FALSE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, DlpNoPref2) {
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
SetDlpPolicy(CHECK_NONE);
DeepScanningDialogDelegate::Data data;
EXPECT_FALSE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, DlpNoPref3) {
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
SetDlpPolicy(CHECK_DOWNLOADS);
DeepScanningDialogDelegate::Data data;
EXPECT_FALSE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, DlpEnabled) {
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
SetDlpPolicy(CHECK_UPLOADS);
DeepScanningDialogDelegate::Data data;
EXPECT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_TRUE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, DlpEnabled2) {
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
SetDlpPolicy(CHECK_UPLOADS_AND_DOWNLOADS);
DeepScanningDialogDelegate::Data data;
EXPECT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_TRUE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, DlpDisabledByList) {
GURL url(kTestUrl);
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
SetDlpPolicy(CHECK_UPLOADS);
AddUrlToList(prefs::kDomainsToNotCheckComplianceOfUploadedContent, url);
DeepScanningDialogDelegate::Data data;
EXPECT_FALSE(DeepScanningDialogDelegate::IsEnabled(profile(), url, &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, MalwareNoPref) {
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
DeepScanningDialogDelegate::Data data;
EXPECT_FALSE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, MalwareNoPref2) {
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
SetMalwarePolicy(DO_NOT_SCAN);
DeepScanningDialogDelegate::Data data;
EXPECT_FALSE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, MalwareNoPref4) {
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
SetMalwarePolicy(SEND_DOWNLOADS);
DeepScanningDialogDelegate::Data data;
EXPECT_FALSE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, MalwareNoList) {
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
SetMalwarePolicy(SEND_UPLOADS);
DeepScanningDialogDelegate::Data data;
EXPECT_FALSE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, MalwareNoList2) {
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
SetMalwarePolicy(SEND_UPLOADS_AND_DOWNLOADS);
DeepScanningDialogDelegate::Data data;
EXPECT_FALSE(DeepScanningDialogDelegate::IsEnabled(profile(), GURL(), &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_FALSE(data.do_malware_scan);
}
TEST_F(DeepScanningDialogDelegateIsEnabledTest, MalwareEnabled) {
GURL url(kTestUrl);
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
SetMalwarePolicy(SEND_UPLOADS_AND_DOWNLOADS);
AddUrlToList(prefs::kDomainsToCheckForMalwareOfUploadedContent, url);
DeepScanningDialogDelegate::Data data;
EXPECT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), url, &data));
EXPECT_FALSE(data.do_dlp_scan);
EXPECT_TRUE(data.do_malware_scan);
}
class DeepScanningDialogDelegateAuditOnlyTest : public BaseTest {
protected:
void RunUntilDone() { run_loop_.Run(); }
content::WebContents* contents() {
if (!web_contents_) {
content::WebContents::CreateParams params(profile());
web_contents_ = content::WebContents::Create(params);
}
return web_contents_.get();
}
void PathFailsDeepScan(base::FilePath path,
DeepScanningClientResponse response) {
failures_.insert({std::move(path), std::move(response)});
}
private:
void SetUp() override {
BaseTest::SetUp();
EnableFeatures({kDeepScanningOfUploads});
SetDMToken(kDmToken);
SetDlpPolicy(CHECK_UPLOADS);
SetMalwarePolicy(SEND_UPLOADS);
DeepScanningDialogDelegate::SetFactoryForTesting(base::BindRepeating(
&FakeDeepScanningDialogDelegate::Create, run_loop_.QuitClosure(),
base::Bind(&DeepScanningDialogDelegateAuditOnlyTest::StatusCallback,
base::Unretained(this)),
kDmToken));
}
DeepScanningClientResponse StatusCallback(const base::FilePath& path) {
// The path succeeds if it is not in the |failures_| maps.
auto it = failures_.find(path);
return it != failures_.end()
? it->second
: FakeDeepScanningDialogDelegate::SuccessfulResponse();
}
base::RunLoop run_loop_;
std::unique_ptr<content::WebContents> web_contents_;
// Paths in this map will be consider to have failed deep scan checks.
// The actual failure response is given for each path.
std::map<base::FilePath, DeepScanningClientResponse> failures_;
};
TEST_F(DeepScanningDialogDelegateAuditOnlyTest, Empty) {
GURL url(kTestUrl);
DeepScanningDialogDelegate::Data data;
ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), url, &data));
// Keep |data| empty by not setting any text or paths.
bool called = false;
DeepScanningDialogDelegate::ShowForWebContents(
contents(), std::move(data),
base::BindOnce(
[](bool* called, const DeepScanningDialogDelegate::Data& data,
const DeepScanningDialogDelegate::Result& result) {
EXPECT_EQ(0u, data.text.size());
EXPECT_EQ(0u, data.paths.size());
EXPECT_EQ(0u, result.text_results.size());
EXPECT_EQ(0u, result.paths_results.size());
*called = true;
},
&called));
RunUntilDone();
EXPECT_TRUE(called);
}
TEST_F(DeepScanningDialogDelegateAuditOnlyTest, StringData) {
GURL url(kTestUrl);
DeepScanningDialogDelegate::Data data;
ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), url, &data));
data.text.emplace_back(base::UTF8ToUTF16("foo"));
bool called = false;
DeepScanningDialogDelegate::ShowForWebContents(
contents(), std::move(data),
base::BindOnce(
[](bool* called, const DeepScanningDialogDelegate::Data& data,
const DeepScanningDialogDelegate::Result& result) {
EXPECT_EQ(1u, data.text.size());
EXPECT_EQ(0u, data.paths.size());
ASSERT_EQ(1u, result.text_results.size());
EXPECT_EQ(0u, result.paths_results.size());
EXPECT_TRUE(result.text_results[0]);
*called = true;
},
&called));
RunUntilDone();
EXPECT_TRUE(called);
}
TEST_F(DeepScanningDialogDelegateAuditOnlyTest, StringData2) {
GURL url(kTestUrl);
DeepScanningDialogDelegate::Data data;
ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), url, &data));
data.text.emplace_back(base::UTF8ToUTF16("foo"));
data.text.emplace_back(base::UTF8ToUTF16("bar"));
bool called = false;
DeepScanningDialogDelegate::ShowForWebContents(
contents(), std::move(data),
base::BindOnce(
[](bool* called, const DeepScanningDialogDelegate::Data& data,
const DeepScanningDialogDelegate::Result& result) {
EXPECT_EQ(2u, data.text.size());
EXPECT_EQ(0u, data.paths.size());
ASSERT_EQ(2u, result.text_results.size());
EXPECT_EQ(0u, result.paths_results.size());
EXPECT_TRUE(result.text_results[0]);
EXPECT_TRUE(result.text_results[1]);
*called = true;
},
&called));
RunUntilDone();
EXPECT_TRUE(called);
}
TEST_F(DeepScanningDialogDelegateAuditOnlyTest, FileData) {
GURL url(kTestUrl);
DeepScanningDialogDelegate::Data data;
ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), url, &data));
data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo"));
bool called = false;
DeepScanningDialogDelegate::ShowForWebContents(
contents(), std::move(data),
base::BindOnce(
[](bool* called, const DeepScanningDialogDelegate::Data& data,
const DeepScanningDialogDelegate::Result& result) {
EXPECT_EQ(0u, data.text.size());
EXPECT_EQ(1u, data.paths.size());
EXPECT_EQ(0u, result.text_results.size());
ASSERT_EQ(1u, result.paths_results.size());
EXPECT_TRUE(result.paths_results[0]);
*called = true;
},
&called));
RunUntilDone();
EXPECT_TRUE(called);
}
TEST_F(DeepScanningDialogDelegateAuditOnlyTest, FileData2) {
GURL url(kTestUrl);
DeepScanningDialogDelegate::Data data;
ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), url, &data));
data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo"));
data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/bar"));
bool called = false;
DeepScanningDialogDelegate::ShowForWebContents(
contents(), std::move(data),
base::BindOnce(
[](bool* called, const DeepScanningDialogDelegate::Data& data,
const DeepScanningDialogDelegate::Result& result) {
EXPECT_EQ(0u, data.text.size());
EXPECT_EQ(2u, data.paths.size());
EXPECT_EQ(0u, result.text_results.size());
ASSERT_EQ(2u, result.paths_results.size());
EXPECT_TRUE(result.paths_results[0]);
EXPECT_TRUE(result.paths_results[1]);
*called = true;
},
&called));
RunUntilDone();
EXPECT_TRUE(called);
}
TEST_F(DeepScanningDialogDelegateAuditOnlyTest, StringFileData) {
GURL url(kTestUrl);
DeepScanningDialogDelegate::Data data;
ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), url, &data));
data.text.emplace_back(base::UTF8ToUTF16("foo"));
data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo"));
data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/bar"));
bool called = false;
DeepScanningDialogDelegate::ShowForWebContents(
contents(), std::move(data),
base::BindOnce(
[](bool* called, const DeepScanningDialogDelegate::Data& data,
const DeepScanningDialogDelegate::Result& result) {
EXPECT_EQ(1u, data.text.size());
EXPECT_EQ(2u, data.paths.size());
ASSERT_EQ(1u, result.text_results.size());
ASSERT_EQ(2u, result.paths_results.size());
EXPECT_TRUE(result.text_results[0]);
EXPECT_TRUE(result.paths_results[0]);
EXPECT_TRUE(result.paths_results[1]);
*called = true;
},
&called));
RunUntilDone();
EXPECT_TRUE(called);
}
TEST_F(DeepScanningDialogDelegateAuditOnlyTest, StringFileDataPartialSuccess) {
SetWaitPolicy(DELAY_UPLOADS);
GURL url(kTestUrl);
DeepScanningDialogDelegate::Data data;
ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), url, &data));
data.text.emplace_back(base::UTF8ToUTF16("foo"));
data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo"));
data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo_fail_malware_1"));
data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo_fail_malware_2"));
data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo_fail_dlp_status"));
data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo_fail_dlp_rule"));
// Mark some files with failed scans.
PathFailsDeepScan(data.paths[1],
FakeDeepScanningDialogDelegate::MalwareResponse(
MalwareDeepScanningVerdict::UWS));
PathFailsDeepScan(data.paths[2],
FakeDeepScanningDialogDelegate::MalwareResponse(
MalwareDeepScanningVerdict::MALWARE));
PathFailsDeepScan(data.paths[3],
FakeDeepScanningDialogDelegate::DlpResponse(
DlpDeepScanningVerdict::FAILURE, "",
DlpDeepScanningVerdict::TriggeredRule::REPORT_ONLY));
PathFailsDeepScan(data.paths[4],
FakeDeepScanningDialogDelegate::DlpResponse(
DlpDeepScanningVerdict::SUCCESS, "rule",
DlpDeepScanningVerdict::TriggeredRule::BLOCK));
bool called = false;
DeepScanningDialogDelegate::ShowForWebContents(
contents(), std::move(data),
base::BindOnce(
[](bool* called, const DeepScanningDialogDelegate::Data& data,
const DeepScanningDialogDelegate::Result& result) {
EXPECT_EQ(1u, data.text.size());
EXPECT_EQ(5u, data.paths.size());
ASSERT_EQ(1u, result.text_results.size());
ASSERT_EQ(5u, result.paths_results.size());
EXPECT_TRUE(result.text_results[0]);
EXPECT_TRUE(result.paths_results[0]);
EXPECT_FALSE(result.paths_results[1]);
EXPECT_FALSE(result.paths_results[2]);
EXPECT_FALSE(result.paths_results[3]);
EXPECT_FALSE(result.paths_results[4]);
*called = true;
},
&called));
RunUntilDone();
EXPECT_TRUE(called);
}
TEST_F(DeepScanningDialogDelegateAuditOnlyTest, EmptyWait) {
SetWaitPolicy(DELAY_UPLOADS);
GURL url(kTestUrl);
DeepScanningDialogDelegate::Data data;
ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), url, &data));
bool called = false;
DeepScanningDialogDelegate::ShowForWebContents(
contents(), std::move(data),
base::BindOnce(
[](bool* called, const DeepScanningDialogDelegate::Data& data,
const DeepScanningDialogDelegate::Result& result) {
EXPECT_EQ(0u, data.text.size());
EXPECT_EQ(0u, data.paths.size());
ASSERT_EQ(0u, result.text_results.size());
ASSERT_EQ(0u, result.paths_results.size());
*called = true;
},
&called));
RunUntilDone();
EXPECT_TRUE(called);
}
} // namespace
} // namespace safe_browsing