// Copyright 2019 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CONTENT_BROWSER_BROWSER_INTERFACE_BROKER_IMPL_H_ #define CONTENT_BROWSER_BROWSER_INTERFACE_BROKER_IMPL_H_ #include "base/memory/raw_ptr.h" #include "content/browser/browser_interface_binders.h" #include "content/browser/mojo_binder_policy_applier.h" #include "mojo/public/cpp/bindings/binder_map.h" #include "mojo/public/cpp/bindings/generic_pending_receiver.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/browser_interface_broker.mojom.h" namespace content { // content's implementation of the BrowserInterfaceBroker interface that binds // interfaces requested by the renderer. Every execution context type (frame, // worker etc) owns an instance and registers appropriate handlers, called // "binders" (see internal::PopulateBinderMap and // internal::PopulateBinderMapWithContext). // // By default, BrowserInterfaceBrokerImpl runs the binder that was registered // for a given interface when the interface is requested. However, in some cases // such as prerendering pages, it may be desirable to defer running the binder, // or take another action. Setting a non-null `MojoBinderPolicyApplier` enables // this behavior. // // Note: BrowserInterfaceBrokerImpl will eventually replace the usage of // InterfaceProvider and browser manifests, as well as DocumentInterfaceBroker. template <typename ExecutionContextHost, typename InterfaceBinderContext> class BrowserInterfaceBrokerImpl : public blink::mojom::BrowserInterfaceBroker { public: explicit BrowserInterfaceBrokerImpl(ExecutionContextHost* host) : host_(host) { // The populate functions here define all the interfaces that will be // exposed through the broker. // // The `host` is a templated type (one of RenderFrameHostImpl, // ServiceWorkerHost, etc.). which allows the populate steps here to call a // set of overloaded functions based on that type. Thus each type of `host` // can expose a different set of interfaces, which is determined statically // at compile time. internal::PopulateBinderMap(host, &binder_map_); internal::PopulateBinderMapWithContext(host, &binder_map_with_context_); } // Disallows copy and move operations. BrowserInterfaceBrokerImpl(const BrowserInterfaceBrokerImpl& other) = delete; BrowserInterfaceBrokerImpl& operator=( const BrowserInterfaceBrokerImpl& other) = delete; BrowserInterfaceBrokerImpl(BrowserInterfaceBrokerImpl&&) = delete; BrowserInterfaceBrokerImpl& operator=(BrowserInterfaceBrokerImpl&&) = delete; // blink::mojom::BrowserInterfaceBroker void GetInterface(mojo::GenericPendingReceiver receiver) override { DCHECK(receiver.interface_name().has_value()); if (!policy_applier_) { BindInterface(std::move(receiver)); } else { std::string interface_name = receiver.interface_name().value(); // base::Unretained is safe because `this` outlives `policy_applier_`. policy_applier_->ApplyPolicyToNonAssociatedBinder( interface_name, base::BindOnce(&BrowserInterfaceBrokerImpl::BindInterface, base::Unretained(this), std::move(receiver))); } } // Sets MojoBinderPolicyApplier to control when to bind interfaces. void ApplyMojoBinderPolicies(MojoBinderPolicyApplier* policy_applier) { DCHECK(policy_applier); DCHECK(!policy_applier_); policy_applier_ = policy_applier; } // Stops applying policies to binding requests. void ReleaseMojoBinderPolicies() { DCHECK(policy_applier_); // Reset `policy_applier_` to disable capability control. policy_applier_ = nullptr; } void GetBinderMapInterfacesForTesting(std::vector<std::string>& out) { binder_map_.GetInterfacesForTesting(out); binder_map_with_context_.GetInterfacesForTesting(out); } private: void BindInterface(mojo::GenericPendingReceiver receiver) { if (!binder_map_.TryBind(&receiver)) { if (!binder_map_with_context_.TryBind(internal::GetContextForHost(host_), &receiver)) { host_->ReportNoBinderForInterface("No binder found for interface " + *receiver.interface_name()); } } } const raw_ptr<ExecutionContextHost> host_; mojo::BinderMap binder_map_; mojo::BinderMapWithContext<InterfaceBinderContext> binder_map_with_context_; // The lifetime of `policy_applier_` is managed by the owner of this instance. // The owner should call `ReleaseMojoBinderPolicies()` when it destroys the // applier. raw_ptr<MojoBinderPolicyApplier> policy_applier_ = nullptr; }; } // namespace content #endif // CONTENT_BROWSER_BROWSER_INTERFACE_BROKER_IMPL_H_