ipc_mojo_bootstrap.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright 2014 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 IPC_IPC_MOJO_BOOTSTRAP_H_
  5. #define IPC_IPC_MOJO_BOOTSTRAP_H_
  6. #include <stdint.h>
  7. #include <memory>
  8. #include "base/component_export.h"
  9. #include "base/memory/ref_counted.h"
  10. #include "base/task/single_thread_task_runner.h"
  11. #include "build/build_config.h"
  12. #include "ipc/ipc.mojom.h"
  13. #include "ipc/ipc_channel.h"
  14. #include "ipc/ipc_listener.h"
  15. #include "mojo/public/cpp/bindings/associated_group.h"
  16. #include "mojo/public/cpp/bindings/associated_remote.h"
  17. #include "mojo/public/cpp/bindings/lib/message_quota_checker.h"
  18. #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
  19. #include "mojo/public/cpp/system/message_pipe.h"
  20. namespace IPC {
  21. // Incoming legacy IPCs have always been dispatched to one of two threads: the
  22. // IO thread (when an installed MessageFilter handles the message), or the
  23. // thread which owns the corresponding ChannelProxy receiving the message. There
  24. // were no other places to route legacy IPC messages, so when a message arrived
  25. // the legacy IPC system would run through its MessageFilters and if the message
  26. // was still unhandled, it would be posted to the ChannelProxy thread for
  27. // further processing.
  28. //
  29. // Mojo on the other hand allows for mutually associated endpoints (that is,
  30. // endpoints which locally share the same message pipe) to span any number of
  31. // threads while still guaranteeing that each endpoint on a given thread
  32. // preserves FIFO order of messages dispatched there. This means that if a
  33. // message arrives carrying a PendingAssociatedRemote/Receiver endpoint, and
  34. // then another message arrives which targets that endpoint, the entire pipe
  35. // will be blocked from dispatch until the endpoint is bound: otherwise we have
  36. // no idea where to dispatch the message such that we can uphold the FIFO
  37. // guarantee between the new endpoint and any other endpoints on the thread it
  38. // ends up binding to.
  39. //
  40. // Channel-associated interfaces share a message pipe with the legacy IPC
  41. // Channel, and in order to avoid nasty surprises during the migration process
  42. // we decided to constrain how incoming Channel-associated endpoints could be
  43. // bound: you must either bind them immediately as they arrive on the IO thread,
  44. // or you must immediately post a task to the ChannelProxy thread to bind them.
  45. // This allows all aforementioned FIFO guaratees to be upheld without ever
  46. // stalling dispatch of legacy IPCs (particularly on the IO thread), because
  47. // when we see a message targeting an unbound endpoint we can safely post it to
  48. // the ChannelProxy's task runner before forging ahead to dispatch subsequent
  49. // messages. No stalling.
  50. //
  51. // As there are some cases where a Channel-associated endpoint really wants to
  52. // receive messages on a different TaskRunner, we want to allow that now. It's
  53. // safe as long as the application can guarantee that the endpoint in question
  54. // will be bound to a task runner *before* any messages are received for that
  55. // endpoint.
  56. //
  57. // HOWEVER, it turns out that we cannot simply adhere to the application's
  58. // wishes when an alternative TaskRunner is provided at binding time: over time
  59. // we have accumulated application code which binds Channel-associated endpoints
  60. // to task runners which -- while running tasks exclusively on the ChannelProxy
  61. // thread -- are not the ChannelProxy's own task runner. Such code now
  62. // implicitly relies on the behavior of Channel-associated interfaces always
  63. // dispatching their messages to the ChannelProxy task runner. This is tracked
  64. // by https://crbug.com/1209188.
  65. //
  66. // Finally, the point: if you really know you want to bind your endpoint to an
  67. // alternative task runner and you can really guarantee that no messages may
  68. // have already arrived for it on the IO thread, you can do the binding within
  69. // the extent of a ScopedAllowOffSequenceChannelAssociatedBindings. This will
  70. // flag the endpoint such that it honors your binding configuration, and its
  71. // incoming messages will actually dispatch to the task runner you provide.
  72. class COMPONENT_EXPORT(IPC) ScopedAllowOffSequenceChannelAssociatedBindings {
  73. public:
  74. ScopedAllowOffSequenceChannelAssociatedBindings();
  75. ~ScopedAllowOffSequenceChannelAssociatedBindings();
  76. private:
  77. const bool outer_flag_;
  78. };
  79. // MojoBootstrap establishes a pair of associated interfaces between two
  80. // processes in Chrome.
  81. //
  82. // Clients should implement MojoBootstrap::Delegate to get the associated pipes
  83. // from MojoBootstrap object.
  84. //
  85. // This lives on IO thread other than Create(), which can be called from
  86. // UI thread as Channel::Create() can be.
  87. class COMPONENT_EXPORT(IPC) MojoBootstrap {
  88. public:
  89. virtual ~MojoBootstrap() {}
  90. // Create the MojoBootstrap instance, using |handle| as the message pipe, in
  91. // mode as specified by |mode|. The result is passed to |delegate|.
  92. static std::unique_ptr<MojoBootstrap> Create(
  93. mojo::ScopedMessagePipeHandle handle,
  94. Channel::Mode mode,
  95. const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
  96. const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner,
  97. const scoped_refptr<mojo::internal::MessageQuotaChecker>& quota_checker);
  98. // Initialize the Channel pipe and interface endpoints. This performs all
  99. // setup except actually starting to read messages off the pipe.
  100. virtual void Connect(
  101. mojo::PendingAssociatedRemote<mojom::Channel>* sender,
  102. mojo::PendingAssociatedReceiver<mojom::Channel>* receiver) = 0;
  103. // Enable incoming messages to start being read off the pipe and routed to
  104. // endpoints. Must not be called until the pending endpoints created by
  105. // Connect() are actually bound somewhere.
  106. virtual void StartReceiving() = 0;
  107. // Stop transmitting messages and start queueing them instead.
  108. virtual void Pause() = 0;
  109. // Stop queuing new messages and start transmitting them instead.
  110. virtual void Unpause() = 0;
  111. // Flush outgoing messages which were queued before Start().
  112. virtual void Flush() = 0;
  113. virtual mojo::AssociatedGroup* GetAssociatedGroup() = 0;
  114. };
  115. } // namespace IPC
  116. #endif // IPC_IPC_MOJO_BOOTSTRAP_H_