blob: 48f599791c4849bc0ef67822b14c7dd875bfe54b [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/test/extension_state_tester.h"
#include "base/memory/raw_ref.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension_set.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
namespace {
constexpr char kEnabledSet[] = "enabled";
constexpr char kDisabledSet[] = "disabled";
constexpr char kTerminatedSet[] = "terminated";
constexpr char kBlocklistedSet[] = "blocklisted";
std::string SetToString(const DisableReasonSet& reasons) {
std::string result;
for (int reason : reasons) {
if (!result.empty()) {
result += ", ";
}
result += base::NumberToString(reason);
}
return result;
}
} // namespace
ExtensionStateTester::ExtensionStateTester(
content::BrowserContext* browser_context)
: registry_(ExtensionRegistry::Get(browser_context)),
prefs_(ExtensionPrefs::Get(browser_context)) {}
ExtensionStateTester::~ExtensionStateTester() = default;
bool ExtensionStateTester::ExpectEnabled(const ExtensionId& extension_id) {
bool success = ExpectOnlyInSet(extension_id, kEnabledSet);
DisableReasonSet disable_reasons = prefs_->GetDisableReasons(extension_id);
if (!disable_reasons.empty()) {
success = false;
ADD_FAILURE() << "Extension '" << extension_id
<< "' had unexpected disable reasons: "
<< SetToString(disable_reasons);
}
return success;
}
bool ExtensionStateTester::ExpectDisabledWithSingleReason(
const ExtensionId& extension_id,
disable_reason::DisableReason expected_reason) {
bool success = ExpectOnlyInSet(extension_id, kDisabledSet);
DisableReasonSet disable_reasons = prefs_->GetDisableReasons(extension_id);
// NOTE(devlin): We could make this more helpful in error logging by having
// a mapping of string -> disable reasons, and comparing the vector.
if (disable_reasons.empty()) {
success = false;
ADD_FAILURE() << "Extension should have disable reason " << expected_reason
<< ", but has no disable reasons.";
} else if (!disable_reasons.contains(expected_reason)) {
success = false;
ADD_FAILURE() << "Extension should have disable reason " << expected_reason
<< ", but instead has disable reasons "
<< SetToString(disable_reasons);
} else if (disable_reasons.size() > 1) {
success = false;
ADD_FAILURE() << "Extension has additional unexpected disable reasons. "
<< "Expected only " << expected_reason << ", but found "
<< SetToString(disable_reasons);
}
// Else, disable reasons are as expected.
return success;
}
bool ExtensionStateTester::ExpectDisabledWithReasons(
const ExtensionId& extension_id,
const DisableReasonSet& expected_reasons) {
bool success = ExpectOnlyInSet(extension_id, kDisabledSet);
DisableReasonSet disable_reasons = prefs_->GetDisableReasons(extension_id);
if (disable_reasons.empty()) {
success = false;
ADD_FAILURE() << "Extension should have disable reasons "
<< SetToString(expected_reasons)
<< ", but has no disable reasons.";
} else if (disable_reasons != expected_reasons) {
success = false;
ADD_FAILURE() << "Extension has different disable reasons than expected. "
<< "Expected " << SetToString(expected_reasons)
<< ", but found " << SetToString(disable_reasons);
}
// Else, disable reasons are as expected.
return success;
}
bool ExtensionStateTester::ExpectBlocklisted(const ExtensionId& extension_id) {
return ExpectOnlyInSet(extension_id, kBlocklistedSet);
}
bool ExtensionStateTester::ExpectTerminated(const ExtensionId& extension_id) {
return ExpectOnlyInSet(extension_id, kTerminatedSet);
}
bool ExtensionStateTester::ExpectOnlyInSet(const ExtensionId& extension_id,
const char* expected_set_name) {
struct {
const raw_ref<const ExtensionSet> extensions;
const char* set_name;
} registry_sets[] = {
{ToRawRef(registry_->enabled_extensions()), kEnabledSet},
{ToRawRef(registry_->disabled_extensions()), kDisabledSet},
{ToRawRef(registry_->terminated_extensions()), kTerminatedSet},
{ToRawRef(registry_->blocklisted_extensions()), kBlocklistedSet},
};
auto get_error = [extension_id](const char* set_name, bool expected_in_set) {
if (expected_in_set) {
return base::StringPrintf(
"Extension with id '%s' was expected in the '%s' registry set,"
" but was not present",
extension_id.c_str(), set_name);
}
return base::StringPrintf(
"Extension with id '%s' was unexpectedly found in the '%s' "
"registry set.",
extension_id.c_str(), set_name);
};
bool succeeded = true;
for (const auto& set : registry_sets) {
bool expected_in_set = set.set_name == expected_set_name;
bool is_in_set = set.extensions->Contains(extension_id);
if (expected_in_set == is_in_set)
continue; // Extension is in the set we expect it.
succeeded = false;
ADD_FAILURE() << get_error(set.set_name, expected_in_set);
}
return succeeded;
}
} // namespace extensions