// Copyright 2020 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_MOJO_BINDER_POLICY_APPLIER_H_ #define CONTENT_BROWSER_MOJO_BINDER_POLICY_APPLIER_H_ #include <string> #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/functional/callback_forward.h" #include "base/memory/raw_ref.h" #include "content/browser/mojo_binder_policy_map_impl.h" #include "content/common/content_export.h" namespace content { // MojoBinderPolicyApplier is a helper class for `BrowserInterfaceBrokerImpl` // which allows control over when to run the binder registered for a // requested interface. This is useful in cases like prerendering pages, where // it can be desirable to defer binding until the page is activated, or take // other actions. // // The action to take for each interface is specified in the given // `MojoBinderPolicyMap`, and kDefer is used when no policy is specified. // // See content/browser/preloading/prerender/README.md for more about capability // control. class CONTENT_EXPORT MojoBinderPolicyApplier { public: enum class Mode { // In the kEnforce mode, MojoBinderPolicyApplier processes binding requests // strictly according to the pre-set policies. kEnforce, // If the page is about to activate, MojoBinderPolicyApplier will switch to // the kPrepareToGrantAll mode, and all non-kGrant binders will be // deferred. kPrepareToGrantAll, // In the kGrantAll mode, MojoBinderPolicyApplier grants all binding // requests regardless of their policies. kGrantAll, }; // `policy_map` must outlive `this` and must not be null. // `cancel_callback` will be executed when ApplyPolicyToBinder() processes a // kCancel interface. MojoBinderPolicyApplier( const MojoBinderPolicyMapImpl* policy_map, base::OnceCallback<void(const std::string& interface_name)> cancel_callback); ~MojoBinderPolicyApplier(); // Returns the instance used by BrowserInterfaceBrokerImpl for same-origin // prerendering pages. This is used when the prerendered page and the page // that triggered the prerendering are same origin. static std::unique_ptr<MojoBinderPolicyApplier> CreateForSameOriginPrerendering( base::OnceCallback<void(const std::string& interface_name)> cancel_closure); // Returns the instance used by BrowserInterfaceBrokerImpl for preview mode. // This is used when a page is shown in preview mode. static std::unique_ptr<MojoBinderPolicyApplier> CreateForPreview( base::OnceCallback<void(const std::string& interface_name)> cancel_closure); // Disallows copy and move operations. MojoBinderPolicyApplier(const MojoBinderPolicyApplier& other) = delete; MojoBinderPolicyApplier& operator=(const MojoBinderPolicyApplier& other) = delete; MojoBinderPolicyApplier(MojoBinderPolicyApplier&&) = delete; MojoBinderPolicyApplier& operator=(MojoBinderPolicyApplier&&) = delete; // Applies `MojoBinderNonAssociatedPolicy` before binding a non-associated // interface. // - In kEnforce mode: // - kGrant: Runs `binder_callback` immediately. // - kDefer: Saves `binder_callback` and runs it when GrantAll() is called. // - kCancel: Drops `binder_callback` and runs `cancel_callback_`. // - kUnexpected: Unimplemented now. // - In the kPrepareToGrantAll mode: // - kGrant: Runs `binder_callback` immediately. // - kDefer, kCancel and kUnexpected: Saves `binder_callback` and runs it // when GrantAll() is called. // - In the kGrantAll mode: this always runs the callback immediately. void ApplyPolicyToNonAssociatedBinder(const std::string& interface_name, base::OnceClosure binder_callback); // Applies `MojoBinderAssociatedPolicy` before binding an associated // interface. Note that this method only applies kCancel and kGrant to // associated intefaces, because messages sent over associated interfaces // cannot be deferred. See // https://chromium.googlesource.com/chromium/src/+/HEAD/mojo/public/cpp/bindings/README.md#Associated-Interfaces // for more information. // Runs the cancellation callback and returns false if kCancel is applied. // Otherwise returns true. bool ApplyPolicyToAssociatedBinder(const std::string& interface_name); // Switches this to the kPrepareToGrantAll mode. void PrepareToGrantAll(); // Runs all deferred binders and runs binder callbacks for all subsequent // requests, i.e., it stops applying the policies. void GrantAll(); // Deletes all deferred binders without running them. void DropDeferredBinders(); private: friend class MojoBinderPolicyApplierTest; // Gets the corresponding policy of the given mojo interface name. MojoBinderNonAssociatedPolicy GetNonAssociatedMojoBinderPolicy( const std::string& interface_name) const; const MojoBinderNonAssociatedPolicy default_policy_ = MojoBinderNonAssociatedPolicy::kDefer; // Maps Mojo interface name to its policy. const raw_ref<const MojoBinderPolicyMapImpl> policy_map_; // Will be executed upon a request for a kCancel interface. base::OnceCallback<void(const std::string& interface_name)> cancel_callback_; Mode mode_ = Mode::kEnforce; // Stores binders which are delayed running. std::vector<base::OnceClosure> deferred_binders_; // Stores binders that can be used to send synchronous messages but // are delayed running. std::vector<base::OnceClosure> deferred_sync_binders_; }; } // namespace content #endif // CONTENT_BROWSER_MOJO_BINDER_POLICY_APPLIER_H_