blob: fd571b276895c4853e6f1eaa52ae91ac80d1b454 [file] [log] [blame]
// Copyright 2020 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 "content/browser/mojo_binder_policy_applier.h"
#include "mojo/public/cpp/bindings/message.h"
namespace content {
MojoBinderPolicyApplier::MojoBinderPolicyApplier(
const MojoBinderPolicyMapImpl* policy_map,
base::OnceCallback<void(const std::string& interface_name)> cancel_callback)
: policy_map_(*policy_map), cancel_callback_(std::move(cancel_callback)) {}
MojoBinderPolicyApplier::~MojoBinderPolicyApplier() = default;
// static
std::unique_ptr<MojoBinderPolicyApplier>
MojoBinderPolicyApplier::CreateForSameOriginPrerendering(
base::OnceCallback<void(const std::string& interface_name)>
cancel_callback) {
return std::make_unique<MojoBinderPolicyApplier>(
MojoBinderPolicyMapImpl::GetInstanceForSameOriginPrerendering(),
std::move(cancel_callback));
}
void MojoBinderPolicyApplier::ApplyPolicyToBinder(
const std::string& interface_name,
base::OnceClosure binder_callback) {
if (mode_ == Mode::kGrantAll) {
std::move(binder_callback).Run();
return;
}
const MojoBinderPolicy policy = GetMojoBinderPolicy(interface_name);
// Run in the kPrepareToGrantAll mode before the renderer sends back a
// DidCommitActivation. In this mode, MojoBinderPolicyApplier loosens
// policies, but still defers binders to ensure that the renderer does not
// receive unexpected messages before CommitActivation arrives.
if (mode_ == Mode::kPrepareToGrantAll) {
switch (policy) {
case MojoBinderPolicy::kGrant:
// Grant these two kinds of interfaces because:
// - kCancel and kUnexpected interfaces may have sync methods, so grant
// them to avoid deadlocks.
// - Renderer might request these interfaces during the prerenderingchange
// event, because from the page's point of view it is no longer
// prerendering.
case MojoBinderPolicy::kCancel:
case MojoBinderPolicy::kUnexpected:
std::move(binder_callback).Run();
break;
case MojoBinderPolicy::kDefer:
deferred_binders_.push_back(std::move(binder_callback));
break;
}
return;
}
DCHECK_EQ(mode_, Mode::kEnforce);
switch (policy) {
case MojoBinderPolicy::kGrant:
std::move(binder_callback).Run();
break;
case MojoBinderPolicy::kCancel:
if (cancel_callback_) {
std::move(cancel_callback_).Run(interface_name);
}
break;
case MojoBinderPolicy::kDefer:
deferred_binders_.push_back(std::move(binder_callback));
break;
case MojoBinderPolicy::kUnexpected:
mojo::ReportBadMessage("MBPA_BAD_INTERFACE: " + interface_name);
if (cancel_callback_) {
std::move(cancel_callback_).Run(interface_name);
}
break;
}
}
void MojoBinderPolicyApplier::PrepareToGrantAll() {
DCHECK_EQ(mode_, Mode::kEnforce);
mode_ = Mode::kPrepareToGrantAll;
}
void MojoBinderPolicyApplier::GrantAll() {
DCHECK_NE(mode_, Mode::kGrantAll);
mode_ = Mode::kGrantAll;
// It's safe to iterate over `deferred_binders_` because no more callbacks
// will be added to it once `grant_all_` is true."
for (auto& deferred_binder : deferred_binders_)
std::move(deferred_binder).Run();
deferred_binders_.clear();
}
void MojoBinderPolicyApplier::DropDeferredBinders() {
deferred_binders_.clear();
}
MojoBinderPolicy MojoBinderPolicyApplier::GetMojoBinderPolicy(
const std::string& interface_name) const {
return policy_map_.GetMojoBinderPolicy(interface_name, default_policy_);
}
} // namespace content