blob: 04fec78567c6ae1be223bb7b406dfa8c1de74aa2 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/enterprise/browser/reporting/report_scheduler.h"
#include <utility>
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/strcat.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/enterprise/reporting/prefs.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/upgrade_detector/build_state.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/device_signals/core/common/signals_features.h"
#include "components/enterprise/browser/controller/fake_browser_dm_token_storage.h"
#include "components/enterprise/browser/reporting/chrome_profile_request_generator.h"
#include "components/enterprise/browser/reporting/common_pref_names.h"
#include "components/enterprise/browser/reporting/report_generation_config.h"
#include "components/enterprise/browser/reporting/report_generator.h"
#include "components/enterprise/browser/reporting/report_request.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/testing_pref_service.h"
#include "components/reporting/client/report_queue_provider.h"
#include "components/reporting/proto/synced/record_constants.pb.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/version_info/version_info.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_ANDROID)
#include "chrome/browser/enterprise/reporting/report_scheduler_android.h"
#include "chrome/browser/enterprise/reporting/reporting_delegate_factory_android.h"
#else
#include "chrome/browser/enterprise/reporting/report_scheduler_desktop.h"
#include "chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h"
#endif // BUILDFLAG(IS_ANDROID)
using ::base::test::RunOnceCallback;
using ::testing::_;
using ::testing::ByMove;
using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::WithArgs;
namespace em = enterprise_management;
namespace enterprise_reporting {
namespace {
constexpr char kDMToken[] = "dm_token";
constexpr char kClientId[] = "client_id";
constexpr base::TimeDelta kUploadFrequency = base::Hours(12);
constexpr base::TimeDelta kNewUploadFrequency = base::Hours(10);
constexpr char kUploadTriggerMetricName[] =
"Enterprise.CloudReportingUploadTrigger";
constexpr char kSignalsReportingModeMetricName[] =
"Enterprise.SecurityReport.User.Mode";
} // namespace
ACTION_P(ScheduleGeneratorCallback, request_number) {
ReportRequestQueue requests;
for (int i = 0; i < request_number; i++)
requests.push(std::make_unique<ReportRequest>(ReportType::kFull));
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(arg0), std::move(requests)));
}
ACTION(ScheduleProfileRequestGeneratorCallback) {
ReportRequestQueue requests;
requests.push(std::make_unique<ReportRequest>(ReportType::kProfileReport));
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(arg0), std::move(requests)));
}
class MockReportGenerator : public ReportGenerator {
public:
#if BUILDFLAG(IS_ANDROID)
explicit MockReportGenerator(
ReportingDelegateFactoryAndroid* delegate_factory)
: ReportGenerator(delegate_factory) {}
#else
explicit MockReportGenerator(
ReportingDelegateFactoryDesktop* delegate_factory)
: ReportGenerator(delegate_factory) {}
#endif // BUILDFLAG(IS_ANDROID)
void Generate(ReportType report_type, ReportCallback callback) override {
OnGenerate(report_type, callback);
}
MOCK_METHOD(void,
OnGenerate,
(ReportType report_type, ReportCallback& callback),
());
MOCK_METHOD(ReportRequestQueue, GenerateBasic, (), ());
};
class MockReportUploader : public ReportUploader {
public:
MockReportUploader() : ReportUploader(nullptr, 0) {}
MockReportUploader(const MockReportUploader&) = delete;
MockReportUploader& operator=(const MockReportUploader&) = delete;
~MockReportUploader() override = default;
MOCK_METHOD(void,
SetRequestAndUpload,
(const ReportGenerationConfig&,
ReportRequestQueue,
ReportCallback),
(override));
};
class MockChromeProfileRequestGenerator : public ChromeProfileRequestGenerator {
public:
#if BUILDFLAG(IS_ANDROID)
explicit MockChromeProfileRequestGenerator(
ReportingDelegateFactoryAndroid* delegate_factory)
#else
explicit MockChromeProfileRequestGenerator(
ReportingDelegateFactoryDesktop* delegate_factory)
#endif // BUILDFLAG(IS_ANDROID)
: ChromeProfileRequestGenerator(/*profile_path=*/base::FilePath(),
delegate_factory) {
}
void Generate(ReportGenerationConfig generation_config,
ReportCallback callback) override {
OnGenerate(callback);
}
MOCK_METHOD(void, OnGenerate, (ReportCallback&), ());
};
class ReportSchedulerTest : public ::testing::Test {
protected:
ReportSchedulerTest()
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
profile_manager_(TestingBrowserProcess::GetGlobal()) {}
ReportSchedulerTest(const ReportSchedulerTest&) = delete;
ReportSchedulerTest& operator=(const ReportSchedulerTest&) = delete;
~ReportSchedulerTest() override = default;
void SetUp() override {
scoped_feature_list_.InitWithFeatureState(
enterprise_signals::features::kProfileSignalsReportingEnabled,
profile_security_signals_enabled());
ASSERT_TRUE(profile_manager_.SetUp());
client_ptr_ = std::make_unique<policy::MockCloudPolicyClient>();
client_ = client_ptr_.get();
generator_ptr_ =
std::make_unique<MockReportGenerator>(&report_delegate_factory_);
generator_ = generator_ptr_.get();
uploader_ptr_ = std::make_unique<MockReportUploader>();
uploader_ = uploader_ptr_.get();
profile_request_generator_ptr_ =
std::make_unique<MockChromeProfileRequestGenerator>(
&report_delegate_factory_);
profile_request_generator_ = profile_request_generator_ptr_.get();
#if !BUILDFLAG(IS_CHROMEOS)
SetLastUploadVersion(chrome::kChromeVersion);
#endif
Init(true, kDMToken, kClientId);
}
void Init(bool policy_enabled,
const std::string& dm_token,
const std::string& client_id) {
ToggleCloudReport(policy_enabled);
#if !BUILDFLAG(IS_CHROMEOS)
storage_.SetDMToken(dm_token);
storage_.SetClientId(client_id);
#endif
}
void CreateScheduler() {
ReportScheduler::CreateParams params;
params.client = client_;
params.delegate = report_delegate_factory_.GetReportSchedulerDelegate();
params.report_generator = std::move(generator_ptr_);
scheduler_ = std::make_unique<ReportScheduler>(std::move(params));
scheduler_->QueueReportUploaderForTesting(std::move(uploader_ptr_));
}
#if !BUILDFLAG(IS_CHROMEOS)
void CreateSchedulerForProfileReporting(Profile* profile) {
ReportScheduler::CreateParams params;
params.client = client_;
client_->SetDMToken("dm-token");
params.delegate =
#if BUILDFLAG(IS_ANDROID)
std::make_unique<ReportSchedulerAndroid>(profile);
#else
std::make_unique<ReportSchedulerDesktop>(profile);
#endif // BUILDFLAG(IS_ANDROID)
params.profile_request_generator =
std::move(profile_request_generator_ptr_);
scheduler_ = std::make_unique<ReportScheduler>(std::move(params));
scheduler_->QueueReportUploaderForTesting(std::move(uploader_ptr_));
}
#endif // !BUILDFLAG(IS_CHROMEOS)
void SetLastUploadInHour(base::TimeDelta gap, Profile* profile = nullptr) {
previous_set_last_upload_timestamp_ = base::Time::Now() - gap;
auto* pref_service =
profile ? profile->GetPrefs()
: TestingBrowserProcess::GetGlobal()->local_state();
pref_service->SetTime(kLastUploadTimestamp,
previous_set_last_upload_timestamp_);
}
void SetReportFrequency(base::TimeDelta frequency) {
TestingBrowserProcess::GetGlobal()->local_state()->SetTimeDelta(
kCloudReportingUploadFrequency, frequency);
}
void ToggleCloudReport(bool enabled) {
TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetManagedPref(
kCloudReportingEnabled, std::make_unique<base::Value>(enabled));
}
#if !BUILDFLAG(IS_CHROMEOS)
void SetLastUploadVersion(const std::string& version) {
TestingBrowserProcess::GetGlobal()->local_state()->SetString(
kLastUploadVersion, version);
}
void ExpectLastUploadVersion(const std::string& version) {
EXPECT_EQ(TestingBrowserProcess::GetGlobal()->local_state()->GetString(
kLastUploadVersion),
version);
}
#endif // !BUILDFLAG(IS_CHROMEOS)
// If lastUploadTimestamp is updated recently, it should be updated as Now().
// Otherwise, it should be same as previous set timestamp.
void ExpectLastUploadTimestampUpdated(bool is_updated) {
auto current_last_upload_timestamp =
TestingBrowserProcess::GetGlobal()->local_state()->GetTime(
kLastUploadTimestamp);
if (is_updated) {
EXPECT_EQ(base::Time::Now(), current_last_upload_timestamp);
} else {
EXPECT_EQ(previous_set_last_upload_timestamp_,
current_last_upload_timestamp);
}
}
ReportRequestQueue CreateRequests(int number) {
ReportRequestQueue requests;
for (int i = 0; i < number; i++)
requests.push(std::make_unique<ReportRequest>(ReportType::kFull));
return requests;
}
// Chrome OS needn't setup registration.
void EXPECT_CALL_SetupRegistration() {
#if BUILDFLAG(IS_CHROMEOS)
EXPECT_CALL(*client_, SetupRegistration(_, _, _)).Times(0);
#else
EXPECT_CALL(*client_, SetupRegistration(kDMToken, kClientId, _))
.WillOnce(WithArgs<0>(
Invoke(client_.get(), &policy::MockCloudPolicyClient::SetDMToken)));
#endif
}
// This function is virtual to allow derived classes to override it and test
// the behavior with the feature enabled/disabled.
virtual bool profile_security_signals_enabled() { return false; }
content::BrowserTaskEnvironment task_environment_;
TestingProfileManager profile_manager_;
#if BUILDFLAG(IS_ANDROID)
ReportingDelegateFactoryAndroid report_delegate_factory_;
#else
ReportingDelegateFactoryDesktop report_delegate_factory_;
#endif // BUILDFLAG(IS_ANDROID)
std::unique_ptr<ReportScheduler> scheduler_;
raw_ptr<policy::MockCloudPolicyClient, DanglingUntriaged> client_;
raw_ptr<MockReportGenerator, DanglingUntriaged> generator_;
raw_ptr<MockReportUploader, DanglingUntriaged> uploader_;
raw_ptr<MockChromeProfileRequestGenerator, DanglingUntriaged>
profile_request_generator_;
#if !BUILDFLAG(IS_CHROMEOS)
policy::FakeBrowserDMTokenStorage storage_;
#endif
base::Time previous_set_last_upload_timestamp_;
base::HistogramTester histogram_tester_;
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<policy::MockCloudPolicyClient> client_ptr_;
std::unique_ptr<MockReportGenerator> generator_ptr_;
std::unique_ptr<MockReportUploader> uploader_ptr_;
std::unique_ptr<MockChromeProfileRequestGenerator>
profile_request_generator_ptr_;
};
TEST_F(ReportSchedulerTest, NoReportWithoutPolicy) {
Init(false, kDMToken, kClientId);
CreateScheduler();
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
}
// Chrome OS needn't set dm token and client id in the report scheduler.
#if !BUILDFLAG(IS_CHROMEOS)
TEST_F(ReportSchedulerTest, NoReportWithoutDMToken) {
Init(true, "", kClientId);
CreateScheduler();
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
}
TEST_F(ReportSchedulerTest, NoReportWithoutClientId) {
Init(true, kDMToken, "");
CreateScheduler();
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
}
#endif
TEST_F(ReportSchedulerTest, UploadReportSucceeded) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(
*uploader_,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerTimer, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
// Next report is scheduled.
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(true);
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
// Profile reporting does not support ChromeOS.
#if !BUILDFLAG(IS_CHROMEOS)
TEST_F(ReportSchedulerTest, UploadReportSucceededForProfileReporting) {
EXPECT_CALL(*profile_request_generator_, OnGenerate(_))
.WillOnce(WithArgs<0>(ScheduleProfileRequestGeneratorCallback()));
EXPECT_CALL(*uploader_,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerTimer,
ReportType::kProfileReport,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
TestingProfile* profile = profile_manager_.CreateTestingProfile("profile");
profile->GetTestingPrefService()->SetManagedPref(
kCloudProfileReportingEnabled, std::make_unique<base::Value>(true));
CreateSchedulerForProfileReporting(profile);
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
// Next report is scheduled.
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
auto current_last_upload_timestamp =
profile->GetPrefs()->GetTime(kLastUploadTimestamp);
EXPECT_EQ(base::Time::Now(), current_last_upload_timestamp);
histogram_tester_.ExpectTotalCount(kSignalsReportingModeMetricName, 0);
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(profile_request_generator_);
}
#endif // !BUILDFLAG(IS_CHROMEOS)
TEST_F(ReportSchedulerTest, UploadReportTransientError) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(
*uploader_,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerTimer, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kTransientError));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
// Next report is scheduled.
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(true);
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, UploadReportPersistentError) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(
*uploader_,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerTimer, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kPersistentError));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
// Next report is not scheduled.
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(false);
// Turn off and on reporting to resume.
ToggleCloudReport(false);
ToggleCloudReport(true);
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, NoReportGenerate) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(0)));
EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _, _)).Times(0);
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
// Next report is not scheduled.
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(false);
// Turn off and on reporting to resume.
ToggleCloudReport(false);
ToggleCloudReport(true);
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, TimerDelayWithLastUploadTimestamp) {
const base::TimeDelta gap = base::Hours(10);
SetLastUploadInHour(gap);
SetReportFrequency(kUploadFrequency);
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(
*uploader_,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerTimer, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
base::TimeDelta next_report_delay = kUploadFrequency - gap;
task_environment_.FastForwardBy(next_report_delay - base::Seconds(1));
ExpectLastUploadTimestampUpdated(false);
task_environment_.FastForwardBy(base::Seconds(1));
ExpectLastUploadTimestampUpdated(true);
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, TimerDelayWithoutLastUploadTimestamp) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(
*uploader_,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerTimer, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(false);
task_environment_.FastForwardBy(base::TimeDelta());
ExpectLastUploadTimestampUpdated(true);
::testing::Mock::VerifyAndClearExpectations(client_);
}
TEST_F(ReportSchedulerTest, TimerDelayUpdate) {
const base::TimeDelta gap = base::Hours(5);
SetLastUploadInHour(gap);
SetReportFrequency(kUploadFrequency);
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(
*uploader_,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerTimer, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
SetReportFrequency(kNewUploadFrequency);
// The report should be re-scheduled, moving the time forward with the new
// interval.
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
base::TimeDelta next_report_delay = kNewUploadFrequency - gap;
task_environment_.FastForwardBy(next_report_delay - base::Seconds(1));
ExpectLastUploadTimestampUpdated(false);
task_environment_.FastForwardBy(base::Seconds(1));
ExpectLastUploadTimestampUpdated(true);
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, IgnoreFrequencyWithoutReportEnabled) {
Init(false, kDMToken, kClientId);
CreateScheduler();
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
SetReportFrequency(kUploadFrequency);
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
// Toggle reporting on and off.
EXPECT_CALL_SetupRegistration();
ToggleCloudReport(true);
ToggleCloudReport(false);
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
SetReportFrequency(kNewUploadFrequency);
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
}
TEST_F(ReportSchedulerTest,
ReportingIsDisabledWhileNewReportIsScheduledButNotPosted) {
EXPECT_CALL_SetupRegistration();
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
ToggleCloudReport(false);
// Next report is not scheduled.
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
ExpectLastUploadTimestampUpdated(false);
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, ReportingIsDisabledWhileNewReportIsPosted) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(
*uploader_,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerTimer, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
CreateScheduler();
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
ToggleCloudReport(false);
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
ExpectLastUploadTimestampUpdated(true);
// Next report is not scheduled.
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
::testing::Mock::VerifyAndClearExpectations(client_);
::testing::Mock::VerifyAndClearExpectations(generator_);
}
TEST_F(ReportSchedulerTest, ManualReport) {
SetLastUploadInHour(base::Hours(1));
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(
*uploader_,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerManual, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
CreateScheduler();
base::MockOnceClosure callback;
EXPECT_CALL(callback, Run()).Times(1);
scheduler_->UploadFullReport(callback.Get());
task_environment_.RunUntilIdle();
ExpectLastUploadTimestampUpdated(true);
histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 6, 1);
histogram_tester_.ExpectTotalCount(kSignalsReportingModeMetricName, 0);
::testing::Mock::VerifyAndClearExpectations(generator_);
::testing::Mock::VerifyAndClearExpectations(uploader_);
}
TEST_F(ReportSchedulerTest, ScheduledReportAfterManualReport) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(
*uploader_,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerManual, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
CreateScheduler();
base::MockOnceClosure callback;
EXPECT_CALL(callback, Run()).Times(1);
// Trigger manual report first and then move forward time to trigger timer
// report.
scheduler_->UploadFullReport(callback.Get());
task_environment_.RunUntilIdle();
ExpectLastUploadTimestampUpdated(true);
histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 6, 1);
::testing::Mock::VerifyAndClearExpectations(generator_);
::testing::Mock::VerifyAndClearExpectations(uploader_);
}
TEST_F(ReportSchedulerTest, ManualReportWithRegularOneOngoing) {
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
// Callback for timer report will be held.
ReportUploader::ReportCallback saved_timer_callback;
EXPECT_CALL(
*uploader_,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerTimer, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce([&saved_timer_callback](
ReportGenerationConfig config, ReportRequestQueue requests,
ReportUploader::ReportCallback callback) {
saved_timer_callback = std::move(callback);
});
CreateScheduler();
// Trigger timer report first.
task_environment_.RunUntilIdle();
base::MockOnceClosure callback;
EXPECT_CALL(callback, Run()).Times(1);
// Trigger manual report and then release timer report callback.
scheduler_->UploadFullReport(callback.Get());
std::move(saved_timer_callback).Run(ReportUploader::kSuccess);
task_environment_.RunUntilIdle();
ExpectLastUploadTimestampUpdated(true);
histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 1, 1);
::testing::Mock::VerifyAndClearExpectations(generator_);
::testing::Mock::VerifyAndClearExpectations(uploader_);
}
// Android does not support version updates
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
// Tests that a basic report is generated and uploaded when a browser update is
// detected.
TEST_F(ReportSchedulerTest, OnUpdate) {
// Pretend that a periodic report was generated recently so that one isn't
// kicked off during startup.
SetLastUploadInHour(base::Hours(1));
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kBrowserVersion, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerUpdate,
ReportType::kBrowserVersion,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
CreateScheduler();
g_browser_process->GetBuildState()->SetUpdate(
BuildState::UpdateType::kNormalUpdate,
base::Version(base::StrCat({"1", version_info::GetVersionNumber()})),
std::nullopt);
task_environment_.RunUntilIdle();
// The timestamp should not have been updated, since a periodic report was not
// generated/uploaded.
ExpectLastUploadTimestampUpdated(false);
histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 2, 1);
}
TEST_F(ReportSchedulerTest, OnUpdateAndPersistentError) {
// Pretend that a periodic report was generated recently so that one isn't
// kicked off during startup.
SetLastUploadInHour(base::Hours(1));
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kBrowserVersion, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerUpdate,
ReportType::kBrowserVersion,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kPersistentError));
CreateScheduler();
g_browser_process->GetBuildState()->SetUpdate(
BuildState::UpdateType::kNormalUpdate,
base::Version(base::StrCat({"1", version_info::GetVersionNumber()})),
std::nullopt);
task_environment_.RunUntilIdle();
// The timestamp should not have been updated, since a periodic report was not
// generated/uploaded.
ExpectLastUploadTimestampUpdated(false);
histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 2, 1);
// The report should be stopped in case of persistent error.
g_browser_process->GetBuildState()->SetUpdate(
BuildState::UpdateType::kNormalUpdate,
base::Version(base::StrCat({"2", version_info::GetVersionNumber()})),
std::nullopt);
histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 2, 1);
}
// Tests that a full report is generated and uploaded following a basic report
// if the timer fires while the basic report is being uploaded.
TEST_F(ReportSchedulerTest, DeferredTimer) {
EXPECT_CALL_SetupRegistration();
CreateScheduler();
// An update arrives, triggering report generation and upload (sans profiles).
EXPECT_CALL(*generator_, OnGenerate(ReportType::kBrowserVersion, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
// Hang on to the uploader's ReportCallback.
ReportUploader::ReportCallback saved_callback;
EXPECT_CALL(*uploader_,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerUpdate,
ReportType::kBrowserVersion,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce([&saved_callback](ReportGenerationConfig config,
ReportRequestQueue requests,
ReportUploader::ReportCallback callback) {
saved_callback = std::move(callback);
});
g_browser_process->GetBuildState()->SetUpdate(
BuildState::UpdateType::kNormalUpdate,
base::Version(base::StrCat({"1", version_info::GetVersionNumber()})),
std::nullopt);
task_environment_.RunUntilIdle();
::testing::Mock::VerifyAndClearExpectations(generator_);
::testing::Mock::VerifyAndClearExpectations(uploader_);
// Now the timer fires before the upload completes. No new report should be
// generated yet.
task_environment_.RunUntilIdle();
::testing::Mock::VerifyAndClearExpectations(generator_);
// Once the previous upload completes, a new report should be generated
// forthwith.
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
auto new_uploader = std::make_unique<MockReportUploader>();
EXPECT_CALL(
*new_uploader,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerTimer, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
std::move(saved_callback).Run(ReportUploader::kSuccess);
ExpectLastUploadTimestampUpdated(false);
::testing::Mock::VerifyAndClearExpectations(generator_);
this->uploader_ = new_uploader.get();
this->scheduler_->QueueReportUploaderForTesting(std::move(new_uploader));
task_environment_.RunUntilIdle();
::testing::Mock::VerifyAndClearExpectations(uploader_);
ExpectLastUploadTimestampUpdated(true);
histogram_tester_.ExpectBucketCount(kUploadTriggerMetricName, 1, 1);
histogram_tester_.ExpectBucketCount(kUploadTriggerMetricName, 2, 1);
}
// Tests that a basic report is generated and uploaded during startup when a
// new version is being run and the last periodic upload was less than a day
// ago.
TEST_F(ReportSchedulerTest, OnNewVersion) {
// Pretend that the last upload was from a different browser version.
SetLastUploadVersion(chrome::kChromeVersion + std::string("1"));
// Pretend that a periodic report was generated recently.
SetLastUploadInHour(base::Hours(1));
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kBrowserVersion, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(*uploader_,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerNewVersion,
ReportType::kBrowserVersion,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
CreateScheduler();
task_environment_.RunUntilIdle();
// The timestamp should not have been updated, since a periodic report was not
// generated/uploaded.
ExpectLastUploadTimestampUpdated(false);
// The last upload is now from this version.
ExpectLastUploadVersion(chrome::kChromeVersion);
histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 3, 1);
}
// Tests that a full report is generated and uploaded during startup when a
// new version is being run and the last periodic upload was more than a day
// ago.
TEST_F(ReportSchedulerTest, OnNewVersionRegularReport) {
// Pretend that the last upload was from a different browser version.
SetLastUploadVersion(chrome::kChromeVersion + std::string("1"));
// Pretend that a periodic report was last generated over a day ago.
SetLastUploadInHour(base::Hours(25));
EXPECT_CALL_SetupRegistration();
EXPECT_CALL(*generator_, OnGenerate(ReportType::kFull, _))
.WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1)));
EXPECT_CALL(
*uploader_,
SetRequestAndUpload(ReportGenerationConfig(
ReportTrigger::kTriggerTimer, ReportType::kFull,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
CreateScheduler();
task_environment_.RunUntilIdle();
// The timestamp should have been updated, since a periodic report was
// generated/uploaded.
ExpectLastUploadTimestampUpdated(true);
// The last upload is now from this version.
ExpectLastUploadVersion(chrome::kChromeVersion);
histogram_tester_.ExpectUniqueSample(kUploadTriggerMetricName, 1, 1);
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
#if !BUILDFLAG(IS_CHROMEOS)
// Profile security signals are not supported on ChromeOS.
class EnabledProfileSecuritySignalsReportSchedulerTest
: public ReportSchedulerTest {
protected:
bool profile_security_signals_enabled() override { return true; }
void SetUserSecuritySignalsPolicy(
TestingProfile* profile,
bool enabled,
std::optional<bool> use_cookies = std::nullopt) {
profile->GetTestingPrefService()->SetManagedPref(
kUserSecuritySignalsReporting, base::Value(enabled));
if (use_cookies) {
profile->GetTestingPrefService()->SetManagedPref(
kUserSecurityAuthenticatedReporting, base::Value(*use_cookies));
}
}
};
// Tests that no cookies will be used as part of the upload when the security
// signals policy is disabled.
TEST_F(EnabledProfileSecuritySignalsReportSchedulerTest,
ProfileReportingEnabled_UserSecuritySignalsPolicyDisabled) {
EXPECT_CALL(*profile_request_generator_, OnGenerate(_))
.WillOnce(WithArgs<0>(ScheduleProfileRequestGeneratorCallback()));
EXPECT_CALL(*uploader_,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerTimer,
ReportType::kProfileReport,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
TestingProfile* profile = profile_manager_.CreateTestingProfile("profile");
SetUserSecuritySignalsPolicy(profile, /*enabled=*/false);
profile->GetTestingPrefService()->SetManagedPref(
kCloudProfileReportingEnabled, std::make_unique<base::Value>(true));
CreateSchedulerForProfileReporting(profile);
ASSERT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
histogram_tester_.ExpectTotalCount(kSignalsReportingModeMetricName, 0);
}
// Tests that cookies will be used as part of the upload when both the security
// signals policy is disabled but kUserSecurityAuthenticatedReporting is
// enabled.
TEST_F(EnabledProfileSecuritySignalsReportSchedulerTest,
ProfileReportingDisabled_UserSecuritySignalsPolicyEnabled_WithCookies) {
EXPECT_CALL(*profile_request_generator_, OnGenerate(_))
.WillOnce(WithArgs<0>(ScheduleProfileRequestGeneratorCallback()));
EXPECT_CALL(*uploader_,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerSecurity,
ReportType::kProfileReport,
SecuritySignalsMode::kSignalsOnly,
/*use_cookies=*/true),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
TestingProfile* profile = profile_manager_.CreateTestingProfile("profile");
SetUserSecuritySignalsPolicy(profile, /*enabled=*/true, /*use_cookies=*/true);
profile->GetTestingPrefService()->SetManagedPref(
kCloudProfileReportingEnabled, std::make_unique<base::Value>(false));
CreateSchedulerForProfileReporting(profile);
// Run pending task.
task_environment_.FastForwardBy(base::TimeDelta());
histogram_tester_.ExpectUniqueSample(kSignalsReportingModeMetricName, 2, 1);
}
// Edge case where:
// - Security signals reporting is disabled, but reporting is turned on
// - Before status report finishes, security signals reporting is enabled, so a
// signals-only report is scheduled
// - We need to make sure that the first report does not affect signals
// reporting timer/trigger, and the signals-only report is generated/uploaded
// afterwards
TEST_F(EnabledProfileSecuritySignalsReportSchedulerTest,
SignalsReportingRaceConditionPrevented) {
TestingProfile* profile = profile_manager_.CreateTestingProfile("profile");
SetUserSecuritySignalsPolicy(profile, /*enabled=*/false);
EXPECT_CALL(*profile_request_generator_, OnGenerate(_))
.Times(2)
.WillRepeatedly(WithArgs<0>(ScheduleProfileRequestGeneratorCallback()));
EXPECT_CALL(*uploader_,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerTimer,
ReportType::kProfileReport,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce([&](const ReportGenerationConfig&, ReportRequestQueue,
ReportUploader::ReportCallback callback) {
// Trigger a signals-only report before the no-signals status report
// finishes generating. This trigger will be added to pending triggers.
SetUserSecuritySignalsPolicy(profile, /*enabled=*/true,
/*use_cookies=*/true);
std::move(callback).Run(ReportUploader::kSuccess);
});
profile->GetTestingPrefService()->SetManagedPref(
kCloudProfileReportingEnabled, std::make_unique<base::Value>(true));
CreateSchedulerForProfileReporting(profile);
ASSERT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Create another uploader for the second upload.
auto second_uploader = std::make_unique<MockReportUploader>();
EXPECT_CALL(*second_uploader,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerSecurity,
ReportType::kProfileReport,
SecuritySignalsMode::kSignalsOnly,
/*use_cookies=*/true),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
scheduler_->QueueReportUploaderForTesting(std::move(second_uploader));
// Trigger a status report without signals, which will then trigger a
// signals-only report before it finishes.
task_environment_.FastForwardBy(base::TimeDelta());
}
// Tests the use-case where a report is being requested manually when profile
// reporting is enabled but not security signals.
TEST_F(EnabledProfileSecuritySignalsReportSchedulerTest,
UploadManualReportSucceededForProfileReporting_NoSecurity) {
EXPECT_CALL(*profile_request_generator_, OnGenerate(_))
.WillOnce(WithArgs<0>(ScheduleProfileRequestGeneratorCallback()));
EXPECT_CALL(*uploader_,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerManual,
ReportType::kProfileReport,
SecuritySignalsMode::kNoSignals,
/*use_cookies=*/false),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
TestingProfile* profile = profile_manager_.CreateTestingProfile("profile");
SetUserSecuritySignalsPolicy(profile, /*enabled=*/false);
profile->GetTestingPrefService()->SetManagedPref(
kCloudProfileReportingEnabled, std::make_unique<base::Value>(true));
SetLastUploadInHour(base::Hours(1), profile);
CreateSchedulerForProfileReporting(profile);
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
base::RunLoop run_loop;
scheduler_->UploadFullReport(run_loop.QuitClosure());
run_loop.Run();
histogram_tester_.ExpectTotalCount(kSignalsReportingModeMetricName, 0);
}
// Tests the use-case where a report is being requested manually when both
// profile reporting and security signals are enabled.
TEST_F(EnabledProfileSecuritySignalsReportSchedulerTest,
UploadManualReportSucceededForProfileReporting_Both) {
// First set of expectations is for the timed security upload.
EXPECT_CALL(*profile_request_generator_, OnGenerate(_))
.WillOnce(WithArgs<0>(ScheduleProfileRequestGeneratorCallback()));
EXPECT_CALL(*uploader_,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerSecurity,
ReportType::kProfileReport,
SecuritySignalsMode::kSignalsOnly,
/*use_cookies=*/true),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
TestingProfile* profile = profile_manager_.CreateTestingProfile("profile");
profile->GetTestingPrefService()->SetManagedPref(
kCloudProfileReportingEnabled, std::make_unique<base::Value>(true));
SetUserSecuritySignalsPolicy(profile, /*enabled=*/true, /*use_cookies=*/true);
SetLastUploadInHour(base::Hours(1), profile);
CreateSchedulerForProfileReporting(profile);
EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task, for the timed security report to get uploaded.
task_environment_.FastForwardBy(base::TimeDelta());
EXPECT_CALL(*profile_request_generator_, OnGenerate(_))
.WillOnce(WithArgs<0>(ScheduleProfileRequestGeneratorCallback()));
// Create another uploader for the second upload.
auto second_uploader = std::make_unique<MockReportUploader>();
EXPECT_CALL(*second_uploader,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerManual,
ReportType::kProfileReport,
SecuritySignalsMode::kSignalsAttached,
/*use_cookies=*/true),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
scheduler_->QueueReportUploaderForTesting(std::move(second_uploader));
base::RunLoop run_loop;
scheduler_->UploadFullReport(run_loop.QuitClosure());
run_loop.Run();
// A status report with signals and a signals-only report
histogram_tester_.ExpectBucketCount(kSignalsReportingModeMetricName, 1, 1);
histogram_tester_.ExpectBucketCount(kSignalsReportingModeMetricName, 2, 1);
}
// Tests the use-case where a report is being requested manually when profile
// reporting is not enabled, but security signals are.
TEST_F(EnabledProfileSecuritySignalsReportSchedulerTest,
UploadManualReportSucceededForProfileReporting_OnlySecurity) {
// First set of expectations is for the timed security upload.
EXPECT_CALL(*profile_request_generator_, OnGenerate(_))
.WillOnce(WithArgs<0>(ScheduleProfileRequestGeneratorCallback()));
EXPECT_CALL(*uploader_,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerSecurity,
ReportType::kProfileReport,
SecuritySignalsMode::kSignalsOnly,
/*use_cookies=*/true),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
TestingProfile* profile = profile_manager_.CreateTestingProfile("profile");
profile->GetTestingPrefService()->SetManagedPref(
kCloudProfileReportingEnabled, std::make_unique<base::Value>(false));
SetUserSecuritySignalsPolicy(profile, /*enabled=*/true, /*use_cookies=*/true);
CreateSchedulerForProfileReporting(profile);
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
// Run pending task, for the timed security report to get uploaded.
task_environment_.FastForwardBy(base::TimeDelta());
EXPECT_CALL(*profile_request_generator_, OnGenerate(_))
.WillOnce(WithArgs<0>(ScheduleProfileRequestGeneratorCallback()));
// Create another uploader for the second upload.
auto second_uploader = std::make_unique<MockReportUploader>();
EXPECT_CALL(*second_uploader,
SetRequestAndUpload(
ReportGenerationConfig(ReportTrigger::kTriggerSecurity,
ReportType::kProfileReport,
SecuritySignalsMode::kSignalsOnly,
/*use_cookies=*/true),
_, _))
.WillOnce(RunOnceCallback<2>(ReportUploader::kSuccess));
scheduler_->QueueReportUploaderForTesting(std::move(second_uploader));
base::RunLoop run_loop;
scheduler_->UploadFullReport(run_loop.QuitClosure());
run_loop.Run();
histogram_tester_.ExpectUniqueSample(kSignalsReportingModeMetricName, 2, 2);
}
// Tests the use-case where a report is being requested manually when neither
// profile reporting nor security signals are enabled.
TEST_F(EnabledProfileSecuritySignalsReportSchedulerTest,
UploadManualReportForProfileReporting_PoliciesDisabled) {
// First set of expectations is for the timed security upload.
TestingProfile* profile = profile_manager_.CreateTestingProfile("profile");
profile->GetTestingPrefService()->SetManagedPref(
kCloudProfileReportingEnabled, std::make_unique<base::Value>(false));
SetUserSecuritySignalsPolicy(profile, /*enabled=*/false);
CreateSchedulerForProfileReporting(profile);
EXPECT_FALSE(scheduler_->IsNextReportScheduledForTesting());
base::RunLoop run_loop;
scheduler_->UploadFullReport(run_loop.QuitClosure());
run_loop.Run();
histogram_tester_.ExpectTotalCount(kSignalsReportingModeMetricName, 0);
}
#endif // !BUILDFLAG(IS_CHROMEOS)
} // namespace enterprise_reporting