123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- // Copyright 2021 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 "android_webview/browser/component_updater/loader_policies/aw_apps_package_names_allowlist_component_loader_policy.h"
- #include <fcntl.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <utility>
- #include "android_webview/browser/metrics/aw_metrics_service_client.h"
- #include "android_webview/common/metrics/app_package_name_logging_rule.h"
- #include "base/containers/flat_map.h"
- #include "base/files/file_path.h"
- #include "base/files/file_util.h"
- #include "base/files/scoped_file.h"
- #include "base/metrics/user_metrics.h"
- #include "base/run_loop.h"
- #include "base/sequence_checker.h"
- #include "base/test/bind.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "base/test/task_environment.h"
- #include "base/time/time.h"
- #include "base/values.h"
- #include "base/version.h"
- #include "components/component_updater/android/component_loader_policy.h"
- #include "components/optimization_guide/core/bloom_filter.h"
- #include "components/prefs/testing_pref_service.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace android_webview {
- using AllowlistPraseStatus =
- AwAppsPackageNamesAllowlistComponentLoaderPolicy::AllowlistPraseStatus;
- namespace {
- constexpr int kNumHash = 11;
- constexpr int kNumBitsPerEntry = 16;
- constexpr char kTestAllowlistVersion[] = "123.456.789.10";
- const std::string kTestAllowlist[] = {"com.example.test", "my.fake.app",
- "yet.another.app"};
- constexpr char kAllowlistPraseStatusHistogramName[] =
- "Android.WebView.Metrics.PackagesAllowList.ParseStatus";
- double MillisFromUnixEpoch(const base::Time& time) {
- return (time - base::Time::UnixEpoch()).InMillisecondsF();
- }
- std::unique_ptr<base::Value> BuildTestManifest() {
- auto manifest = std::make_unique<base::Value>(base::Value::Type::DICTIONARY);
- manifest->SetKey(kBloomFilterNumHashKey, base::Value(kNumHash));
- manifest->SetKey(kBloomFilterNumBitsKey, base::Value(3 * kNumBitsPerEntry));
- manifest->SetKey(
- kExpiryDateKey,
- base::Value(MillisFromUnixEpoch(base::Time::Now() + base::Days(1))));
- return manifest;
- }
- } // namespace
- class AwAppsPackageNamesAllowlistComponentLoaderPolicyTest
- : public ::testing::Test {
- public:
- void SetUp() override {
- ASSERT_TRUE(base::CreateTemporaryFile(&allowlist_path_));
- }
- void TearDown() override {
- base::DeleteFile(allowlist_path_);
- }
- void WriteAllowListToFile(const std::vector<uint8_t>& data) {
- ASSERT_TRUE(base::WriteFile(allowlist_path_, data));
- }
- void WritePackageNamesAllowListToFile() {
- auto filter = std::make_unique<optimization_guide::BloomFilter>(
- kNumHash, kNumBitsPerEntry * std::size(kTestAllowlist));
- for (const auto& package : kTestAllowlist) {
- filter->Add(package);
- }
- WriteAllowListToFile(filter->bytes());
- }
- base::ScopedFD OpenAndGetAllowlistFd() {
- int allowlist_fd = open(allowlist_path_.value().c_str(), O_RDONLY);
- CHECK(allowlist_fd) << "Failed to open FD for " << allowlist_path_;
- return base::ScopedFD(allowlist_fd);
- }
- void LookupConfirmationCallback(
- absl::optional<AppPackageNameLoggingRule> record) {
- EXPECT_TRUE(checker_.CalledOnValidSequence());
- allowlist_lookup_result_ = record;
- lookup_run_loop_.Quit();
- }
- protected:
- base::test::TaskEnvironment env_;
- // Has to be init after TaskEnvironment.
- base::SequenceCheckerImpl checker_;
- base::RunLoop lookup_run_loop_;
- base::HistogramTester histogram_tester_;
- absl::optional<AppPackageNameLoggingRule> allowlist_lookup_result_;
- private:
- base::FilePath allowlist_path_;
- };
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestExistingPackageName) {
- WritePackageNamesAllowListToFile();
- base::flat_map<std::string, base::ScopedFD> fd_map;
- fd_map[kAllowlistBloomFilterFileName] = OpenAndGetAllowlistFd();
- std::unique_ptr<base::Value> manifest = BuildTestManifest();
- base::Time one_day_from_now = base::Time::Now() + base::Days(1);
- manifest->SetDoubleKey(kExpiryDateKey, MillisFromUnixEpoch(one_day_from_now));
- base::Version new_version(kTestAllowlistVersion);
- auto policy =
- std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
- kTestAllowlist[1],
- AppPackageNameLoggingRule(base::Version("123.456.789.0"),
- base::Time::Min()),
- base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
- LookupConfirmationCallback,
- base::Unretained(this)));
- policy->ComponentLoaded(new_version, fd_map,
- base::DictionaryValue::From(std::move(manifest)));
- lookup_run_loop_.Run();
- ASSERT_TRUE(allowlist_lookup_result_.has_value());
- EXPECT_TRUE(allowlist_lookup_result_.value().IsAppPackageNameAllowed());
- EXPECT_EQ(allowlist_lookup_result_.value().GetVersion(), new_version);
- EXPECT_EQ(allowlist_lookup_result_.value().GetExpiryDate(), one_day_from_now);
- histogram_tester_.ExpectBucketCount(kAllowlistPraseStatusHistogramName,
- AllowlistPraseStatus::kSuccess, 1);
- histogram_tester_.ExpectTotalCount(kAllowlistPraseStatusHistogramName, 1);
- }
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestSameVersionAsCache) {
- base::flat_map<std::string, base::ScopedFD> fd_map;
- std::unique_ptr<base::Value> manifest = BuildTestManifest();
- base::Time one_day_from_now = base::Time::Now() + base::Days(1);
- base::Version version(kTestAllowlistVersion);
- AppPackageNameLoggingRule expected_record(version, one_day_from_now);
- auto policy =
- std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
- "test.some.app", expected_record,
- base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
- LookupConfirmationCallback,
- base::Unretained(this)));
- policy->ComponentLoaded(version, fd_map,
- base::DictionaryValue::From(std::move(manifest)));
- lookup_run_loop_.Run();
- ASSERT_TRUE(allowlist_lookup_result_.has_value());
- EXPECT_TRUE(allowlist_lookup_result_.value().IsAppPackageNameAllowed());
- EXPECT_TRUE(expected_record.IsSameAs(allowlist_lookup_result_.value()));
- histogram_tester_.ExpectBucketCount(kAllowlistPraseStatusHistogramName,
- AllowlistPraseStatus::kUsingCache, 1);
- histogram_tester_.ExpectTotalCount(kAllowlistPraseStatusHistogramName, 1);
- }
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestNonExistingPackageName) {
- WritePackageNamesAllowListToFile();
- base::flat_map<std::string, base::ScopedFD> fd_map;
- fd_map[kAllowlistBloomFilterFileName] = OpenAndGetAllowlistFd();
- base::Version new_version(kTestAllowlistVersion);
- auto policy =
- std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
- "non.existent.app", absl::optional<AppPackageNameLoggingRule>(),
- base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
- LookupConfirmationCallback,
- base::Unretained(this)));
- policy->ComponentLoaded(new_version, fd_map,
- base::DictionaryValue::From(BuildTestManifest()));
- lookup_run_loop_.Run();
- ASSERT_TRUE(allowlist_lookup_result_.has_value());
- EXPECT_EQ(allowlist_lookup_result_.value().GetVersion(), new_version);
- EXPECT_FALSE(allowlist_lookup_result_.value().IsAppPackageNameAllowed());
- histogram_tester_.ExpectBucketCount(kAllowlistPraseStatusHistogramName,
- AllowlistPraseStatus::kSuccess, 1);
- histogram_tester_.ExpectTotalCount(kAllowlistPraseStatusHistogramName, 1);
- }
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestAllowlistFileNotInMap) {
- base::flat_map<std::string, base::ScopedFD> fd_map;
- fd_map["another_file"] = OpenAndGetAllowlistFd();
- auto policy =
- std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
- kTestAllowlist[1], absl::optional<AppPackageNameLoggingRule>(),
- base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
- LookupConfirmationCallback,
- base::Unretained(this)));
- policy->ComponentLoaded(base::Version(kTestAllowlistVersion), fd_map,
- base::DictionaryValue::From(BuildTestManifest()));
- lookup_run_loop_.Run();
- EXPECT_FALSE(allowlist_lookup_result_.has_value());
- histogram_tester_.ExpectBucketCount(
- kAllowlistPraseStatusHistogramName,
- AllowlistPraseStatus::kMissingAllowlistFile, 1);
- histogram_tester_.ExpectTotalCount(kAllowlistPraseStatusHistogramName, 1);
- }
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestMissingBloomFilterParams) {
- WritePackageNamesAllowListToFile();
- base::flat_map<std::string, base::ScopedFD> fd_map;
- fd_map[kAllowlistBloomFilterFileName] = OpenAndGetAllowlistFd();
- auto policy =
- std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
- kTestAllowlist[1], absl::optional<AppPackageNameLoggingRule>(),
- base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
- LookupConfirmationCallback,
- base::Unretained(this)));
- policy->ComponentLoaded(base::Version(kTestAllowlistVersion), fd_map,
- std::make_unique<base::DictionaryValue>());
- lookup_run_loop_.Run();
- EXPECT_FALSE(allowlist_lookup_result_.has_value());
- histogram_tester_.ExpectBucketCount(kAllowlistPraseStatusHistogramName,
- AllowlistPraseStatus::kMissingFields, 1);
- histogram_tester_.ExpectTotalCount(kAllowlistPraseStatusHistogramName, 1);
- }
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestTooShortBloomFilter) {
- WriteAllowListToFile(std::vector<uint8_t>(2, 0xff));
- base::flat_map<std::string, base::ScopedFD> fd_map;
- fd_map[kAllowlistBloomFilterFileName] = OpenAndGetAllowlistFd();
- auto policy =
- std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
- kTestAllowlist[1], absl::optional<AppPackageNameLoggingRule>(),
- base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
- LookupConfirmationCallback,
- base::Unretained(this)));
- policy->ComponentLoaded(base::Version(kTestAllowlistVersion), fd_map,
- base::DictionaryValue::From(BuildTestManifest()));
- lookup_run_loop_.Run();
- EXPECT_FALSE(allowlist_lookup_result_.has_value());
- histogram_tester_.ExpectBucketCount(
- kAllowlistPraseStatusHistogramName,
- AllowlistPraseStatus::kMalformedBloomFilter, 1);
- histogram_tester_.ExpectTotalCount(kAllowlistPraseStatusHistogramName, 1);
- }
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestTooLongBloomFilter) {
- WriteAllowListToFile(std::vector<uint8_t>(2000, 0xff));
- base::flat_map<std::string, base::ScopedFD> fd_map;
- fd_map[kAllowlistBloomFilterFileName] = OpenAndGetAllowlistFd();
- auto policy =
- std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
- kTestAllowlist[1], absl::optional<AppPackageNameLoggingRule>(),
- base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
- LookupConfirmationCallback,
- base::Unretained(this)));
- policy->ComponentLoaded(base::Version(kTestAllowlistVersion), fd_map,
- base::DictionaryValue::From(BuildTestManifest()));
- lookup_run_loop_.Run();
- EXPECT_FALSE(allowlist_lookup_result_.has_value());
- histogram_tester_.ExpectBucketCount(
- kAllowlistPraseStatusHistogramName,
- AllowlistPraseStatus::kMalformedBloomFilter, 1);
- histogram_tester_.ExpectTotalCount(kAllowlistPraseStatusHistogramName, 1);
- }
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestExpiredAllowlist) {
- WritePackageNamesAllowListToFile();
- base::flat_map<std::string, base::ScopedFD> fd_map;
- fd_map[kAllowlistBloomFilterFileName] = OpenAndGetAllowlistFd();
- std::unique_ptr<base::Value> manifest = BuildTestManifest();
- manifest->SetKey(
- kExpiryDateKey,
- base::Value(MillisFromUnixEpoch(base::Time::Now() - base::Days(1))));
- auto policy =
- std::make_unique<AwAppsPackageNamesAllowlistComponentLoaderPolicy>(
- kTestAllowlist[1], absl::optional<AppPackageNameLoggingRule>(),
- base::BindOnce(&AwAppsPackageNamesAllowlistComponentLoaderPolicyTest::
- LookupConfirmationCallback,
- base::Unretained(this)));
- policy->ComponentLoaded(base::Version(kTestAllowlistVersion), fd_map,
- base::DictionaryValue::From(std::move(manifest)));
- lookup_run_loop_.Run();
- EXPECT_FALSE(allowlist_lookup_result_.has_value());
- histogram_tester_.ExpectBucketCount(kAllowlistPraseStatusHistogramName,
- AllowlistPraseStatus::kExpiredAllowlist,
- 1);
- histogram_tester_.ExpectTotalCount(kAllowlistPraseStatusHistogramName, 1);
- }
- // Helper functions for throttling tests, defining them near tests body for
- // better readability.
- namespace {
- class AwMetricsServiceClientTestDelegate
- : public AwMetricsServiceClient::Delegate {
- void RegisterAdditionalMetricsProviders(
- metrics::MetricsService* service) override {}
- void AddWebViewAppStateObserver(WebViewAppStateObserver* observer) override {}
- bool HasAwContentsEverCreated() const override { return false; }
- };
- void TestThrottling(base::Time time,
- AwMetricsServiceClient* client,
- bool expect_throttling) {
- if (!time.is_null()) {
- client->SetAppPackageNameLoggingRuleLastUpdateTime(time);
- }
- component_updater::ComponentLoaderPolicyVector policies;
- LoadPackageNamesAllowlistComponent(policies, client);
- EXPECT_EQ(policies.size(), expect_throttling ? 0 : 1u);
- }
- void TestThrottlingAllowlist(absl::optional<AppPackageNameLoggingRule> rule,
- bool expect_throttling) {
- TestingPrefServiceSimple prefs;
- AwMetricsServiceClient::RegisterMetricsPrefs(prefs.registry());
- AwMetricsServiceClient client(
- std::make_unique<AwMetricsServiceClientTestDelegate>());
- client.Initialize(&prefs);
- client.SetAppPackageNameLoggingRule(rule);
- // No previous last_update record: should never throttle.
- TestThrottling(base::Time(), &client, /*expect_throttling=*/false);
- // last_update record > max_throttle_time : should never throttle.
- TestThrottling(base::Time::Now() - kWebViewAppsMaxAllowlistThrottleTimeDelta -
- base::Days(1),
- &client,
- /*expect_throttling=*/false);
- // min_throttle_time < last_update record < max_throttle_time : maybe
- // throttle.
- TestThrottling(base::Time::Now() - kWebViewAppsMaxAllowlistThrottleTimeDelta +
- kWebViewAppsMinAllowlistThrottleTimeDelta,
- &client,
- /*expect_throttling=*/expect_throttling);
- // last_update record < min_throttle_time : should always throttle.
- TestThrottling(base::Time::Now() - kWebViewAppsMinAllowlistThrottleTimeDelta +
- base::Minutes(30),
- &client,
- /*expect_throttling=*/true);
- }
- } // namespace
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestThrottlingAllowlist_AbsentCache) {
- base::SetRecordActionTaskRunner(env_.GetMainThreadTaskRunner());
- TestThrottlingAllowlist(absl::optional<AppPackageNameLoggingRule>(),
- /*expect_throttling=*/false);
- }
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestThrottlingAllowlist_ValidCacheAllowedApp) {
- base::SetRecordActionTaskRunner(env_.GetMainThreadTaskRunner());
- TestThrottlingAllowlist(
- AppPackageNameLoggingRule(base::Version(kTestAllowlistVersion),
- base::Time::Now() + base::Days(1)),
- /*expect_throttling=*/true);
- }
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestThrottlingAllowlist_ValidCacheNotAllowedApp) {
- base::SetRecordActionTaskRunner(env_.GetMainThreadTaskRunner());
- TestThrottlingAllowlist(
- AppPackageNameLoggingRule(base::Version(kTestAllowlistVersion),
- base::Time::Min()),
- /*expect_throttling=*/true);
- }
- TEST_F(AwAppsPackageNamesAllowlistComponentLoaderPolicyTest,
- TestThrottlingAllowlist_ExpiredAllowedCache) {
- base::SetRecordActionTaskRunner(env_.GetMainThreadTaskRunner());
- TestThrottlingAllowlist(
- AppPackageNameLoggingRule(base::Version(kTestAllowlistVersion),
- base::Time::Now() - base::Days(1)),
- /*expect_throttling=*/false);
- }
- } // namespace android_webview
|