1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136

content / browser / mojo_binder_policy_applier.h [blame]

// 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_