blob: e7b0cd73c4b603a89f485493ac346f1be28c53b5 [file] [log] [blame]
// Copyright 2019 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/enterprise/reporting/report_request_queue_generator.h"
#include <vector>
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h"
#include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/account_id/account_id.h"
#include "components/enterprise/browser/reporting/browser_report_generator.h"
#include "components/enterprise/browser/reporting/report_request_definition.h"
#include "components/policy/core/common/mock_policy_service.h"
#include "components/policy/core/common/policy_map.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension_builder.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace em = enterprise_management;
namespace enterprise_reporting {
namespace {
const char kIdleProfileName1[] = "idle_profile1";
const char kIdleProfileName2[] = "idle_profile2";
const char kActiveProfileName1[] = "active_profile1";
const char kActiveProfileName2[] = "active_profile2";
} // namespace
class ReportRequestQueueGeneratorTest : public ::testing::Test {
public:
using ReportRequest = definition::ReportRequest;
ReportRequestQueueGeneratorTest()
: profile_manager_(TestingBrowserProcess::GetGlobal()),
browser_report_generator_(&reporting_delegate_factory_),
report_request_queue_generator_(&reporting_delegate_factory_) {}
~ReportRequestQueueGeneratorTest() override = default;
void SetUp() override {
ASSERT_TRUE(profile_manager_.SetUp());
profile_manager_.CreateGuestProfile();
profile_manager_.CreateSystemProfile();
content::PluginService::GetInstance()->Init();
}
std::set<std::string> CreateIdleProfiles() {
CreateIdleProfile(kIdleProfileName1);
CreateIdleProfile(kIdleProfileName2);
return std::set<std::string>{kIdleProfileName1, kIdleProfileName2};
}
std::set<std::string> CreateActiveProfiles() {
CreateActiveProfile(kActiveProfileName1);
CreateActiveProfile(kActiveProfileName2);
return std::set<std::string>{kActiveProfileName1, kActiveProfileName2};
}
std::set<std::string> CreateActiveProfilesWithContent() {
CreateActiveProfileWithContent(kActiveProfileName1);
CreateActiveProfileWithContent(kActiveProfileName2);
return std::set<std::string>{kActiveProfileName1, kActiveProfileName2};
}
void CreateIdleProfile(std::string profile_name) {
profile_manager_.profile_attributes_storage()->AddProfile(
profile_manager()->profiles_dir().AppendASCII(profile_name),
base::ASCIIToUTF16(profile_name), std::string(), base::string16(),
false, 0, std::string(), EmptyAccountId());
}
TestingProfile* CreateActiveProfile(std::string profile_name) {
return profile_manager_.CreateTestingProfile(profile_name);
}
TestingProfile* CreateActiveProfileWithPolicies(
std::string profile_name,
std::unique_ptr<policy::PolicyService> policy_service) {
return profile_manager_.CreateTestingProfile(
profile_name, {}, base::UTF8ToUTF16(profile_name), 0, {},
TestingProfile::TestingFactories(), base::nullopt,
std::move(policy_service));
}
void CreateActiveProfileWithContent(std::string profile_name) {
TestingProfile* active_profile = CreateActiveProfile(profile_name);
extensions::ExtensionRegistry* extension_registry =
extensions::ExtensionRegistry::Get(active_profile);
std::string extension_name =
"a super super super super super super super super super super super "
"super super super super super super long extension name";
extension_registry->AddEnabled(
extensions::ExtensionBuilder(extension_name)
.SetID("abcdefghijklmnoabcdefghijklmnoab")
.Build());
}
std::unique_ptr<ReportRequest> GenerateBasicRequest() {
auto request = std::make_unique<ReportRequest>();
base::RunLoop run_loop;
browser_report_generator_.Generate(base::BindLambdaForTesting(
[&run_loop, &request](std::unique_ptr<em::BrowserReport> report) {
request->set_allocated_browser_report(report.release()),
run_loop.Quit();
}));
run_loop.Run();
return request;
}
std::vector<std::unique_ptr<ReportRequest>> GenerateRequests(
const ReportRequest& request) {
histogram_tester_ = std::make_unique<base::HistogramTester>();
std::queue<std::unique_ptr<ReportRequest>> requests =
report_request_queue_generator_.Generate(request);
std::vector<std::unique_ptr<ReportRequest>> result;
while (!requests.empty()) {
result.push_back(std::move(requests.front()));
requests.pop();
}
VerifyMetrics(result);
return result;
}
void SetAndVerifyMaximumRequestSize(size_t size) {
report_request_queue_generator_.SetMaximumReportSizeForTesting(size);
EXPECT_EQ(size,
report_request_queue_generator_.GetMaximumReportSizeForTesting());
}
void VerifyProfiles(const em::BrowserReport& report,
const std::set<std::string>& idle_profile_names,
const std::set<std::string>& active_profile_names) {
EXPECT_EQ((size_t)report.chrome_user_profile_infos_size(),
idle_profile_names.size() + active_profile_names.size());
std::set<std::string> mutable_idle_profile_names(idle_profile_names);
std::set<std::string> mutable_active_profile_names(active_profile_names);
std::string profiles_dir = profile_manager_.profiles_dir().AsUTF8Unsafe();
for (auto profile : report.chrome_user_profile_infos()) {
// Verify the generated profile id, whose mapping rule varies in
// different cases.
// - Idle: <profiles_dir>/<profile_name>
// - Active: <profiles_dir>/u-<profile_name>-hash
EXPECT_EQ(0u, profile.id().find(profiles_dir));
EXPECT_LE(0u, profile.id().find(profile.name()));
if (profile.is_full_report())
FindAndRemove(mutable_active_profile_names, profile.name());
else
FindAndRemove(mutable_idle_profile_names, profile.name());
}
EXPECT_TRUE(mutable_idle_profile_names.empty());
EXPECT_TRUE(mutable_active_profile_names.empty());
}
void VerifyMetrics(
const std::vector<std::unique_ptr<ReportRequest>>& requests) {
histogram_tester_->ExpectUniqueSample(
"Enterprise.CloudReportingRequestCount", requests.size(), 1);
histogram_tester_->ExpectUniqueSample(
"Enterprise.CloudReportingBasicRequestSize",
/*basic request size floor to KB*/ 0, 1);
}
TestingProfileManager* profile_manager() { return &profile_manager_; }
ReportRequestQueueGenerator* report_request_queue_generator() {
return &report_request_queue_generator_;
}
base::HistogramTester* histogram_tester() { return histogram_tester_.get(); }
private:
void FindAndRemove(std::set<std::string>& names, const std::string& name) {
auto it = names.find(name);
EXPECT_NE(names.end(), it);
names.erase(it);
}
content::BrowserTaskEnvironment task_environment_;
TestingProfileManager profile_manager_;
ReportingDelegateFactoryDesktop reporting_delegate_factory_;
BrowserReportGenerator browser_report_generator_;
ReportRequestQueueGenerator report_request_queue_generator_;
std::unique_ptr<base::HistogramTester> histogram_tester_;
DISALLOW_COPY_AND_ASSIGN(ReportRequestQueueGeneratorTest);
};
TEST_F(ReportRequestQueueGeneratorTest, GenerateReport) {
auto idle_profile_names = CreateIdleProfiles();
auto basic_request = GenerateBasicRequest();
auto requests = GenerateRequests(*basic_request);
EXPECT_EQ(1u, requests.size());
VerifyProfiles(requests[0]->browser_report(), idle_profile_names, {});
histogram_tester()->ExpectBucketCount("Enterprise.CloudReportingRequestSize",
/*report size floor to KB*/ 0, 1);
}
TEST_F(ReportRequestQueueGeneratorTest, GenerateActiveProfiles) {
auto idle_profile_names = CreateIdleProfiles();
auto active_profile_names = CreateActiveProfiles();
auto basic_request = GenerateBasicRequest();
auto requests = GenerateRequests(*basic_request);
EXPECT_EQ(1u, requests.size());
VerifyProfiles(requests[0]->browser_report(), idle_profile_names,
active_profile_names);
histogram_tester()->ExpectBucketCount("Enterprise.CloudReportingRequestSize",
/*report size floor to KB*/ 0, 1);
}
TEST_F(ReportRequestQueueGeneratorTest, BasicReportIsTooBig) {
// Set a super small limitation.
SetAndVerifyMaximumRequestSize(5);
// Because the limitation is so small, no request can be created.
CreateIdleProfiles();
auto basic_request = GenerateBasicRequest();
auto requests = GenerateRequests(*basic_request);
EXPECT_EQ(0u, requests.size());
histogram_tester()->ExpectTotalCount("Enterprise.CloudReportingRequestSize",
0);
}
TEST_F(ReportRequestQueueGeneratorTest, ReportSeparation) {
CreateActiveProfilesWithContent();
auto basic_request = GenerateBasicRequest();
auto requests = GenerateRequests(*basic_request);
EXPECT_EQ(1u, requests.size());
// Set the limitation just below the size of the report so that it needs to be
// separated into two requests later.
SetAndVerifyMaximumRequestSize(requests[0]->ByteSizeLong() - 30);
requests = GenerateRequests(*basic_request);
EXPECT_EQ(2u, requests.size());
// The first profile is activated in the first request only while the second
// profile is activated in the second request.
VerifyProfiles(requests[0]->browser_report(), {kActiveProfileName1},
{kActiveProfileName2});
VerifyProfiles(requests[1]->browser_report(), {kActiveProfileName2},
{kActiveProfileName1});
histogram_tester()->ExpectBucketCount("Enterprise.CloudReportingRequestSize",
/*report size floor to KB*/ 0, 2);
}
TEST_F(ReportRequestQueueGeneratorTest, ProfileReportIsTooBig) {
CreateActiveProfileWithContent(kActiveProfileName1);
auto basic_request = GenerateBasicRequest();
auto requests = GenerateRequests(*basic_request);
EXPECT_EQ(1u, requests.size());
// Set the limitation just below the size of the report.
SetAndVerifyMaximumRequestSize(requests[0]->ByteSizeLong() - 30);
// Add a smaller Profile.
CreateActiveProfile(kActiveProfileName2);
basic_request = GenerateBasicRequest();
requests = GenerateRequests(*basic_request);
EXPECT_EQ(1u, requests.size());
// Only the second Profile is activated while the first one is too big to be
// reported.
VerifyProfiles(requests[0]->browser_report(), {kActiveProfileName1},
{kActiveProfileName2});
histogram_tester()->ExpectBucketCount("Enterprise.CloudReportingRequestSize",
/*report size floor to KB*/ 0, 2);
}
TEST_F(ReportRequestQueueGeneratorTest, ChromePoliciesCollection) {
auto policy_service = std::make_unique<policy::MockPolicyService>();
policy::PolicyMap policy_map;
ON_CALL(*policy_service.get(),
GetPolicies(::testing::Eq(policy::PolicyNamespace(
policy::POLICY_DOMAIN_CHROME, std::string()))))
.WillByDefault(::testing::ReturnRef(policy_map));
policy_map.Set("kPolicyName1", policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(std::vector<base::Value>()),
nullptr);
policy_map.Set("kPolicyName2", policy::POLICY_LEVEL_RECOMMENDED,
policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_MERGED,
std::make_unique<base::Value>(true), nullptr);
CreateActiveProfileWithPolicies(kActiveProfileName1,
std::move(policy_service));
auto basic_request = GenerateBasicRequest();
auto requests = GenerateRequests(*basic_request);
EXPECT_EQ(1u, requests.size());
auto browser_report = requests[0]->browser_report();
EXPECT_EQ(1, browser_report.chrome_user_profile_infos_size());
auto profile_info = browser_report.chrome_user_profile_infos(0);
#if defined(OS_CHROMEOS)
// In Chrome OS, the collection of policies is disabled.
EXPECT_EQ(0, profile_info.chrome_policies_size());
#else
// In desktop Chrome, the collection of policies is enabled.
EXPECT_EQ(2, profile_info.chrome_policies_size());
#endif
}
} // namespace enterprise_reporting