blob: 018374917e343fc229da91879e9124d60e78cc46 [file] [log] [blame]
// Copyright 2022 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/browser/network_permissions_updater.h"
#include "base/barrier_closure.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/cors_origin_pattern_setter.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/common/cors_util.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
namespace extensions {
namespace {
void SetCorsOriginAccessListForExtensionHelper(
const std::vector<content::BrowserContext*>& browser_contexts,
const Extension& extension,
std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
std::vector<network::mojom::CorsOriginPatternPtr> block_patterns,
base::OnceClosure closure) {
auto barrier_closure =
BarrierClosure(browser_contexts.size(), std::move(closure));
for (content::BrowserContext* browser_context : browser_contexts) {
// SetCorsOriginAccessListForExtensionHelper should only affect an incognito
// profile if the extension is actually allowed to run in an incognito
// profile (not just by the extension manifest, but also by user
// preferences).
if (browser_context->IsOffTheRecord())
DCHECK(util::IsIncognitoEnabled(extension.id(), browser_context));
content::CorsOriginPatternSetter::Set(
browser_context, extension.origin(), mojo::Clone(allow_patterns),
mojo::Clone(block_patterns), barrier_closure);
}
}
} // namespace
NetworkPermissionsUpdater::NetworkPermissionsUpdater(
PassKey pass_key,
content::BrowserContext& browser_context,
base::OnceClosure completion_callback)
: browser_context_(&browser_context),
completion_callback_(std::move(completion_callback)) {}
NetworkPermissionsUpdater::~NetworkPermissionsUpdater() = default;
// static
void NetworkPermissionsUpdater::UpdateExtension(
content::BrowserContext& browser_context,
const Extension& extension,
ContextSet context_set,
base::OnceClosure completion_callback) {
auto updater = std::make_unique<NetworkPermissionsUpdater>(
PassKey(), browser_context, std::move(completion_callback));
auto* updater_raw = updater.get();
// The callback takes ownership of `updater`, ensuring it's deleted when
// the update completes.
updater_raw->UpdateExtension(
extension, context_set,
base::BindOnce(&NetworkPermissionsUpdater::OnOriginAccessUpdated,
std::move(updater)));
}
// static
void NetworkPermissionsUpdater::UpdateAllExtensions(
content::BrowserContext& browser_context,
base::OnceClosure completion_callback) {
auto updater = std::make_unique<NetworkPermissionsUpdater>(
PassKey(), browser_context, std::move(completion_callback));
auto* updater_raw = updater.get();
const ExtensionSet& extensions =
ExtensionRegistry::Get(&browser_context)->enabled_extensions();
// The `barrier_closure` takes ownership of `updater`, ensuring it's deleted
// when the update completes.
base::RepeatingClosure barrier_closure = base::BarrierClosure(
extensions.size(),
base::BindOnce(&NetworkPermissionsUpdater::OnOriginAccessUpdated,
std::move(updater)));
// When updating all extensions, we always use "all related contexts".
constexpr ContextSet kContextSet = ContextSet::kAllRelatedContexts;
for (const auto& extension : extensions) {
updater_raw->UpdateExtension(*extension, kContextSet, barrier_closure);
}
}
void NetworkPermissionsUpdater::ResetOriginAccessForExtension(
content::BrowserContext& browser_context,
const Extension& extension) {
SetCorsOriginAccessListForExtensionHelper({&browser_context}, extension, {},
{}, base::DoNothing());
}
void NetworkPermissionsUpdater::UpdateExtension(
const Extension& extension,
ContextSet context_set,
base::OnceClosure completion_callback) {
std::vector<content::BrowserContext*> target_contexts;
if (context_set == ContextSet::kCurrentContextOnly) {
target_contexts = {browser_context_.get()};
} else {
DCHECK_EQ(ContextSet::kAllRelatedContexts, context_set);
target_contexts =
ExtensionsBrowserClient::Get()->GetRelatedContextsForExtension(
browser_context_, extension);
}
SetCorsOriginAccessListForExtensionHelper(
target_contexts, extension, CreateCorsOriginAccessAllowList(extension),
CreateCorsOriginAccessBlockList(extension),
std::move(completion_callback));
}
// static
void NetworkPermissionsUpdater::OnOriginAccessUpdated(
std::unique_ptr<NetworkPermissionsUpdater> updater) {
std::move(updater->completion_callback_).Run();
}
} // namespace extensions