mojo_trap.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef MOJO_CORE_IPCZ_DRIVER_MOJO_TRAP_H_
  5. #define MOJO_CORE_IPCZ_DRIVER_MOJO_TRAP_H_
  6. #include <cstdint>
  7. #include "base/containers/flat_map.h"
  8. #include "base/containers/span.h"
  9. #include "base/memory/scoped_refptr.h"
  10. #include "base/synchronization/lock.h"
  11. #include "mojo/core/ipcz_driver/object.h"
  12. #include "mojo/public/c/system/trap.h"
  13. #include "mojo/public/c/system/types.h"
  14. #include "third_party/ipcz/include/ipcz/ipcz.h"
  15. namespace mojo::core::ipcz_driver {
  16. // Mojo traps are more complex than ipcz traps. A Mojo trap is approximately
  17. // equivalent to a *collection* of ipcz traps (which Mojo would call "triggers"
  18. // within a trap) sharing a common event handler.
  19. //
  20. // A Mojo trap can only be armed while all of its triggers' conditions are
  21. // simultaneously unsatisfied. This object emulates that behavior well enough to
  22. // suit Chromium's needs.
  23. class MojoTrap : public Object<MojoTrap> {
  24. public:
  25. explicit MojoTrap(MojoTrapEventHandler handler);
  26. static Type object_type() { return kMojoTrap; }
  27. // Registers a new trigger on this trap. Each trigger corresponds to an active
  28. // ipcz trap when this Mojo trap is armed.
  29. MojoResult AddTrigger(MojoHandle handle,
  30. MojoHandleSignals signals,
  31. MojoTriggerCondition condition,
  32. uintptr_t trigger_context);
  33. // Unregisters a trigger from the trap. If the trigger still has an ipcz trap
  34. // installed on `handle`, any event it may eventually fire will be ignored.
  35. MojoResult RemoveTrigger(uintptr_t trigger_context);
  36. // Attempts to arm this Mojo trap. Successful arming means that for every
  37. // trigger added, we can install a corresponding ipcz trap.
  38. MojoResult Arm(MojoTrapEvent* blocking_events, uint32_t* num_blocking_events);
  39. // ObjectBase:
  40. void Close() override;
  41. private:
  42. struct Trigger;
  43. ~MojoTrap() override;
  44. static void TrapEventHandler(const IpczTrapEvent* event);
  45. static void TrapRemovalEventHandler(const IpczTrapEvent* event);
  46. void HandleEvent(const IpczTrapEvent& event);
  47. void HandleTrapRemoved(const IpczTrapEvent& event);
  48. // Attempts to arm a single trigger by creating an ipcz trap for it.
  49. IpczResult ArmTrigger(Trigger& trigger,
  50. IpczTrapConditionFlags* satisfied_flags,
  51. IpczPortalStatus* status);
  52. void NotifyTriggerRemoved(Trigger&);
  53. const MojoTrapEventHandler handler_;
  54. base::Lock lock_;
  55. using TriggerMap = base::flat_map<uintptr_t, scoped_refptr<Trigger>>;
  56. TriggerMap triggers_ GUARDED_BY(lock_);
  57. // Trigger prioritization proceeds in a round-robin fashion across consecutive
  58. // Arm() invocations. This iterator caches the most recently prioritized
  59. // entry.
  60. //
  61. // SUBTLE: Because it is invalidated by mutations to `triggers_`, this MUST
  62. // be reset any time a trigger is inserted or removed.
  63. TriggerMap::iterator next_trigger_ GUARDED_BY(lock_) = triggers_.end();
  64. bool armed_ GUARDED_BY(lock_) = false;
  65. };
  66. } // namespace mojo::core::ipcz_driver
  67. #endif // MOJO_CORE_IPCZ_DRIVER_MOJO_TRAP_H_