blob: 60dc73cfb43210a62d4810d774873c35169cf2c0 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/one_shot_event.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/test/browser_test.h"
#include "extensions/browser/extension_function_registry.h"
#include "extensions/browser/extension_system.h"
namespace extensions {
using ExtensionFunctionRegistrationTest = ExtensionBrowserTest;
// Test that all functions are registered with unique names, histogram values,
// and factories. This is a browser test (rather than a unit test) to (help)
// ensure that all the optional factories and services are indeed instantiated.
IN_PROC_BROWSER_TEST_F(ExtensionFunctionRegistrationTest,
CheckForDuplicateEntries) {
// Verify the ExtensionSystem is ready (and thus all extension functions
// registered) before checking.
base::RunLoop run_loop;
ExtensionSystem::Get(profile())->ready().Post(FROM_HERE,
run_loop.QuitClosure());
run_loop.Run();
const ExtensionFunctionRegistry::FactoryMap& factories =
ExtensionFunctionRegistry::GetInstance().GetFactoriesForTesting();
// Sanity check: Many, many functions should have been registered.
EXPECT_GT(factories.size(), 500u);
std::set<std::string> seen_names;
std::map<functions::HistogramValue, std::string> seen_histograms;
// The following are methods that are undocumented and may or may not ship
// with a final API. We allow them to use the UNKNOWN histogram entry in the
// meantime.
// Each entry should have a bug number associated with it.
static const constexpr char* kAllowedUnknownHistogramEntries[] = {
// https://crbug.com/1339382.
"offscreen.hasDocument",
};
for (const auto& key_value : factories) {
const ExtensionFunctionRegistry::FactoryEntry& entry = key_value.second;
SCOPED_TRACE(entry.function_name_);
EXPECT_TRUE(seen_names.insert(entry.function_name_).second);
// NOTE: We explicitly don't check the factory here. On certain platforms
// with enough compiler optimization, the templated factories are re-used
// for different functions.
// EXPECT_TRUE(seen_factories.insert(entry.factory_).second);
if (entry.histogram_value_ == functions::UNKNOWN) {
// The chrome.test API uses UNKNOWN; it's only used in tests.
if (base::StartsWith(entry.function_name_, "test.",
base::CompareCase::SENSITIVE)) {
continue;
}
// Some undocumented, unlaunched APIs may also use UNKNOWN if it's unclear
// (or unlikely) if they will ever launch.
if (base::Contains(kAllowedUnknownHistogramEntries,
std::string(entry.function_name_))) {
continue;
}
ADD_FAILURE() << "Un-allowlisted API found using UNKNOWN histogram entry."
<< entry.function_name_;
} else {
bool is_success =
seen_histograms.emplace(entry.histogram_value_, entry.function_name_)
.second;
if (!is_success) {
ADD_FAILURE() << "Histogram " << entry.function_name_ << " with value "
<< entry.histogram_value_
<< " already exists with another name - "
<< seen_histograms.find(entry.histogram_value_)->second;
}
}
}
}
} // namespace extensions