Commit 4261a7e3 authored by Lukasz Anforowicz's avatar Lukasz Anforowicz Committed by Commit Bot

Ability to force CORB extensions allowlist to be empty.

This gives extension authors a way to test whether their extension
is ready to be removed from the allowlist.

Bug: 846346
Change-Id: Ide112dab32076ac2a554115b7ca815a23385050c
Reviewed-on: https://chromium-review.googlesource.com/c/1368783
Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#619559}
parent 12b64787
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "base/command_line.h"
#include "base/containers/flat_set.h" #include "base/containers/flat_set.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/metrics/field_trial_params.h" #include "base/metrics/field_trial_params.h"
...@@ -28,6 +29,7 @@ ...@@ -28,6 +29,7 @@
#include "extensions/common/extension_features.h" #include "extensions/common/extension_features.h"
#include "extensions/common/extension_set.h" #include "extensions/common/extension_set.h"
#include "extensions/common/manifest_handlers/content_scripts_handler.h" #include "extensions/common/manifest_handlers/content_scripts_handler.h"
#include "extensions/common/switches.h"
#include "extensions/common/user_script.h" #include "extensions/common/user_script.h"
#include "services/network/public/cpp/features.h" #include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_context.mojom.h"
...@@ -139,44 +141,51 @@ bool IsValidHashedExtensionId(const std::string& hash) { ...@@ -139,44 +141,51 @@ bool IsValidHashedExtensionId(const std::string& hash) {
return correct_chars && correct_length; return correct_chars && correct_length;
} }
std::vector<std::string> CreateExtensionAllowlist() {
std::vector<std::string> allowlist;
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kForceEmptyCorbAllowlist)) {
return allowlist;
}
// Make sure kHardcodedPartOfAllowlist will fit, but also leave some room
// for field trial params.
allowlist.reserve(base::size(kHardcodedPartOfCorbAllowlist) + 10);
// Append extensions from the hardcoded allowlist.
for (const char* hash : kHardcodedPartOfCorbAllowlist) {
DCHECK(IsValidHashedExtensionId(hash)); // It also validates the length.
allowlist.push_back(std::string(hash, kHashedExtensionIdLength));
}
// Append extensions from the field trial param.
std::string field_trial_arg = base::GetFieldTrialParamValueByFeature(
extensions_features::kBypassCorbOnlyForExtensionsAllowlist,
extensions_features::kBypassCorbAllowlistParamName);
field_trial_arg = base::ToUpperASCII(field_trial_arg);
std::vector<std::string> field_trial_allowlist = base::SplitString(
field_trial_arg, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
base::EraseIf(field_trial_allowlist, [](const std::string& hash) {
// Filter out invalid data from |field_trial_allowlist|.
if (IsValidHashedExtensionId(hash))
return false; // Don't remove.
LOG(ERROR) << "Invalid extension hash: " << hash;
return true; // Remove.
});
std::move(field_trial_allowlist.begin(), field_trial_allowlist.end(),
std::back_inserter(allowlist));
return allowlist;
}
// Returns a set of HashedExtensionId of extensions that depend on relaxed CORB // Returns a set of HashedExtensionId of extensions that depend on relaxed CORB
// behavior in their content scripts. // behavior in their content scripts.
const base::flat_set<std::string>& GetExtensionsAllowlist() { const base::flat_set<std::string>& GetExtensionsAllowlist() {
DCHECK(base::FeatureList::IsEnabled( DCHECK(base::FeatureList::IsEnabled(
extensions_features::kBypassCorbOnlyForExtensionsAllowlist)); extensions_features::kBypassCorbOnlyForExtensionsAllowlist));
static const base::NoDestructor<base::flat_set<std::string>> s_allowlist([] { static const base::NoDestructor<base::flat_set<std::string>> s_allowlist([] {
std::vector<std::string> allowlist; base::flat_set<std::string> result(CreateExtensionAllowlist());
// Make sure kHardcodedPartOfAllowlist will fit, but also leave some room
// for field trial params.
allowlist.reserve(base::size(kHardcodedPartOfCorbAllowlist) + 10);
// Append extensions from the hardcoded allowlist.
for (const char* hash : kHardcodedPartOfCorbAllowlist) {
DCHECK(IsValidHashedExtensionId(hash)); // It also validates the length.
allowlist.push_back(std::string(hash, kHashedExtensionIdLength));
}
// Append extensions from the field trial param.
std::string field_trial_arg = base::GetFieldTrialParamValueByFeature(
extensions_features::kBypassCorbOnlyForExtensionsAllowlist,
extensions_features::kBypassCorbAllowlistParamName);
field_trial_arg = base::ToUpperASCII(field_trial_arg);
std::vector<std::string> field_trial_allowlist = base::SplitString(
field_trial_arg, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
base::EraseIf(field_trial_allowlist, [](const std::string& hash) {
// Filter out invalid data from |field_trial_allowlist|.
if (IsValidHashedExtensionId(hash))
return false; // Don't remove.
LOG(ERROR) << "Invalid extension hash: " << hash;
return true; // Remove.
});
std::move(field_trial_allowlist.begin(), field_trial_allowlist.end(),
std::back_inserter(allowlist));
// Return as a flat_set.
base::flat_set<std::string> result(std::move(allowlist));
result.shrink_to_fit(); result.shrink_to_fit();
return result; return result;
}()); }());
......
...@@ -64,6 +64,12 @@ const char kExtensionsOnChromeURLs[] = "extensions-on-chrome-urls"; ...@@ -64,6 +64,12 @@ const char kExtensionsOnChromeURLs[] = "extensions-on-chrome-urls";
// Whether to force developer mode extensions highlighting. // Whether to force developer mode extensions highlighting.
const char kForceDevModeHighlighting[] = "force-dev-mode-highlighting"; const char kForceDevModeHighlighting[] = "force-dev-mode-highlighting";
// Whether |extensions_features::kBypassCorbAllowlistParamName| should always be
// empty (i.e. ignoring hardcoded allowlist and the field trial param). This
// switch is useful for manually verifying if an extension would continue to
// work fine after removing it from the allowlist.
const char kForceEmptyCorbAllowlist[] = "force-empty-corb-allowlist";
// Comma-separated list of paths to apps to load at startup. The first app in // Comma-separated list of paths to apps to load at startup. The first app in
// the list will be launched. // the list will be launched.
const char kLoadApps[] = "load-apps"; const char kLoadApps[] = "load-apps";
......
...@@ -25,6 +25,7 @@ extern const char kErrorConsole[]; ...@@ -25,6 +25,7 @@ extern const char kErrorConsole[];
extern const char kExtensionProcess[]; extern const char kExtensionProcess[];
extern const char kExtensionsOnChromeURLs[]; extern const char kExtensionsOnChromeURLs[];
extern const char kForceDevModeHighlighting[]; extern const char kForceDevModeHighlighting[];
extern const char kForceEmptyCorbAllowlist[];
extern const char kLoadApps[]; extern const char kLoadApps[];
extern const char kLoadExtension[]; extern const char kLoadExtension[];
#if defined(CHROMIUM_BUILD) #if defined(CHROMIUM_BUILD)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment