one_time_message_handler.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // Copyright 2017 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 EXTENSIONS_RENDERER_ONE_TIME_MESSAGE_HANDLER_H_
  5. #define EXTENSIONS_RENDERER_ONE_TIME_MESSAGE_HANDLER_H_
  6. #include <memory>
  7. #include <string>
  8. #include "base/memory/weak_ptr.h"
  9. #include "extensions/renderer/bindings/api_binding_types.h"
  10. #include "v8/include/v8-forward.h"
  11. namespace gin {
  12. class Arguments;
  13. }
  14. namespace extensions {
  15. class NativeExtensionBindingsSystem;
  16. class ScriptContext;
  17. struct Message;
  18. struct MessageTarget;
  19. struct PortId;
  20. // A class for handling one-time message communication, including
  21. // runtime.sendMessage and extension.sendRequest. These methods use the same
  22. // underlying architecture as long-lived port-based communications (like
  23. // runtime.connect), but are exposed through a simpler API.
  24. // A basic flow will be from an "opener" (the original sender) and a "receiver"
  25. // (the event listener), which will be in two separate contexts (and potentially
  26. // renderer processes). The flow is outlined below:
  27. //
  28. // chrome.runtime.sendMessage( // initiates the sendMessage flow, triggering
  29. // // SendMessage().
  30. // {foo: bar}, // The data sent with SendMessage().
  31. // function() { ... }); // The response callback in SendMessage().
  32. //
  33. // This creates a new opener port in the context, and posts a message to it
  34. // with the data. The browser then dispatches this to other renderers.
  35. //
  36. // In another context, we have:
  37. // chrome.runtime.onMessage.addListener(function(message, sender, reply) {
  38. // ...
  39. // reply(...);
  40. // });
  41. //
  42. // When the renderer receives the connection message, we will create a
  43. // new receiver port in this context via AddReceiver().
  44. // When the message comes in, we reply with DeliverMessage() to the receiver's
  45. // port ID.
  46. // If the receiver replies via the reply callback, it will send a new message
  47. // back along the port to the browser. The browser then sends this message back
  48. // to the opener's renderer, where it is delivered via DeliverMessage().
  49. //
  50. // This concludes the one-time message flow.
  51. class OneTimeMessageHandler {
  52. public:
  53. explicit OneTimeMessageHandler(
  54. NativeExtensionBindingsSystem* bindings_system);
  55. OneTimeMessageHandler(const OneTimeMessageHandler&) = delete;
  56. OneTimeMessageHandler& operator=(const OneTimeMessageHandler&) = delete;
  57. ~OneTimeMessageHandler();
  58. // Returns true if the given context has a port with the specified id.
  59. bool HasPort(ScriptContext* script_context, const PortId& port_id);
  60. // Initiates a flow to send a message from the given |script_context|. Returns
  61. // the associated promise if this is a promise based request, otherwise
  62. // returns an empty promise.
  63. v8::Local<v8::Promise> SendMessage(ScriptContext* script_context,
  64. const PortId& new_port_id,
  65. const MessageTarget& target_id,
  66. const std::string& method_name,
  67. const Message& message,
  68. binding::AsyncResponseType async_type,
  69. v8::Local<v8::Function> response_callback);
  70. // Adds a receiving port port to the given |script_context| in preparation
  71. // for receiving a message to post to the onMessage event.
  72. void AddReceiver(ScriptContext* script_context,
  73. const PortId& target_port_id,
  74. v8::Local<v8::Object> sender,
  75. const std::string& event_name);
  76. // Delivers a message to the port, either the event listener or in response
  77. // to the sender, if one exists with the specified |target_port_id|. Returns
  78. // true if a message was delivered (i.e., an open channel existed), and false
  79. // otherwise.
  80. bool DeliverMessage(ScriptContext* script_context,
  81. const Message& message,
  82. const PortId& target_port_id);
  83. // Disconnects the port in the context, if one exists with the specified
  84. // |target_port_id|. Returns true if a port was disconnected (i.e., an open
  85. // channel existed), and false otherwise.
  86. bool Disconnect(ScriptContext* script_context,
  87. const PortId& port_id,
  88. const std::string& error_message);
  89. // Gets the number of pending callbacks on the associated per context data for
  90. // testing purposes.
  91. int GetPendingCallbackCountForTest(ScriptContext* script_context);
  92. private:
  93. // Helper methods to deliver a message to an opener/receiver.
  94. bool DeliverMessageToReceiver(ScriptContext* script_context,
  95. const Message& message,
  96. const PortId& target_port_id);
  97. bool DeliverReplyToOpener(ScriptContext* script_context,
  98. const Message& message,
  99. const PortId& target_port_id);
  100. // Helper methods to disconnect an opener/receiver.
  101. bool DisconnectReceiver(ScriptContext* script_context, const PortId& port_id);
  102. bool DisconnectOpener(ScriptContext* script_context,
  103. const PortId& port_id,
  104. const std::string& error_message);
  105. // Triggered when a receiver responds to a message.
  106. void OnOneTimeMessageResponse(const PortId& port_id,
  107. gin::Arguments* arguments);
  108. // Triggered when the callback for replying is garbage collected. Used to
  109. // clean up data that was stored for the callback and for closing the
  110. // associated message port. |raw_callback| is a raw pointer to the associated
  111. // OneTimeMessageCallback, needed for finding and erasing it from the
  112. // OneTimeMessageContextData.
  113. void OnResponseCallbackCollected(ScriptContext* script_context,
  114. const PortId& port_id,
  115. void* raw_callback);
  116. // Called when the messaging event has been dispatched with the result of the
  117. // listeners.
  118. void OnEventFired(const PortId& port_id,
  119. v8::Local<v8::Context> context,
  120. v8::MaybeLocal<v8::Value> result);
  121. // The associated bindings system. Outlives this object.
  122. NativeExtensionBindingsSystem* const bindings_system_;
  123. base::WeakPtrFactory<OneTimeMessageHandler> weak_factory_{this};
  124. };
  125. } // namespace extensions
  126. #endif // EXTENSIONS_RENDERER_ONE_TIME_MESSAGE_HANDLER_H_