123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- // Copyright 2017 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef EXTENSIONS_RENDERER_ONE_TIME_MESSAGE_HANDLER_H_
- #define EXTENSIONS_RENDERER_ONE_TIME_MESSAGE_HANDLER_H_
- #include <memory>
- #include <string>
- #include "base/memory/weak_ptr.h"
- #include "extensions/renderer/bindings/api_binding_types.h"
- #include "v8/include/v8-forward.h"
- namespace gin {
- class Arguments;
- }
- namespace extensions {
- class NativeExtensionBindingsSystem;
- class ScriptContext;
- struct Message;
- struct MessageTarget;
- struct PortId;
- // A class for handling one-time message communication, including
- // runtime.sendMessage and extension.sendRequest. These methods use the same
- // underlying architecture as long-lived port-based communications (like
- // runtime.connect), but are exposed through a simpler API.
- // A basic flow will be from an "opener" (the original sender) and a "receiver"
- // (the event listener), which will be in two separate contexts (and potentially
- // renderer processes). The flow is outlined below:
- //
- // chrome.runtime.sendMessage( // initiates the sendMessage flow, triggering
- // // SendMessage().
- // {foo: bar}, // The data sent with SendMessage().
- // function() { ... }); // The response callback in SendMessage().
- //
- // This creates a new opener port in the context, and posts a message to it
- // with the data. The browser then dispatches this to other renderers.
- //
- // In another context, we have:
- // chrome.runtime.onMessage.addListener(function(message, sender, reply) {
- // ...
- // reply(...);
- // });
- //
- // When the renderer receives the connection message, we will create a
- // new receiver port in this context via AddReceiver().
- // When the message comes in, we reply with DeliverMessage() to the receiver's
- // port ID.
- // If the receiver replies via the reply callback, it will send a new message
- // back along the port to the browser. The browser then sends this message back
- // to the opener's renderer, where it is delivered via DeliverMessage().
- //
- // This concludes the one-time message flow.
- class OneTimeMessageHandler {
- public:
- explicit OneTimeMessageHandler(
- NativeExtensionBindingsSystem* bindings_system);
- OneTimeMessageHandler(const OneTimeMessageHandler&) = delete;
- OneTimeMessageHandler& operator=(const OneTimeMessageHandler&) = delete;
- ~OneTimeMessageHandler();
- // Returns true if the given context has a port with the specified id.
- bool HasPort(ScriptContext* script_context, const PortId& port_id);
- // Initiates a flow to send a message from the given |script_context|. Returns
- // the associated promise if this is a promise based request, otherwise
- // returns an empty promise.
- v8::Local<v8::Promise> SendMessage(ScriptContext* script_context,
- const PortId& new_port_id,
- const MessageTarget& target_id,
- const std::string& method_name,
- const Message& message,
- binding::AsyncResponseType async_type,
- v8::Local<v8::Function> response_callback);
- // Adds a receiving port port to the given |script_context| in preparation
- // for receiving a message to post to the onMessage event.
- void AddReceiver(ScriptContext* script_context,
- const PortId& target_port_id,
- v8::Local<v8::Object> sender,
- const std::string& event_name);
- // Delivers a message to the port, either the event listener or in response
- // to the sender, if one exists with the specified |target_port_id|. Returns
- // true if a message was delivered (i.e., an open channel existed), and false
- // otherwise.
- bool DeliverMessage(ScriptContext* script_context,
- const Message& message,
- const PortId& target_port_id);
- // Disconnects the port in the context, if one exists with the specified
- // |target_port_id|. Returns true if a port was disconnected (i.e., an open
- // channel existed), and false otherwise.
- bool Disconnect(ScriptContext* script_context,
- const PortId& port_id,
- const std::string& error_message);
- // Gets the number of pending callbacks on the associated per context data for
- // testing purposes.
- int GetPendingCallbackCountForTest(ScriptContext* script_context);
- private:
- // Helper methods to deliver a message to an opener/receiver.
- bool DeliverMessageToReceiver(ScriptContext* script_context,
- const Message& message,
- const PortId& target_port_id);
- bool DeliverReplyToOpener(ScriptContext* script_context,
- const Message& message,
- const PortId& target_port_id);
- // Helper methods to disconnect an opener/receiver.
- bool DisconnectReceiver(ScriptContext* script_context, const PortId& port_id);
- bool DisconnectOpener(ScriptContext* script_context,
- const PortId& port_id,
- const std::string& error_message);
- // Triggered when a receiver responds to a message.
- void OnOneTimeMessageResponse(const PortId& port_id,
- gin::Arguments* arguments);
- // Triggered when the callback for replying is garbage collected. Used to
- // clean up data that was stored for the callback and for closing the
- // associated message port. |raw_callback| is a raw pointer to the associated
- // OneTimeMessageCallback, needed for finding and erasing it from the
- // OneTimeMessageContextData.
- void OnResponseCallbackCollected(ScriptContext* script_context,
- const PortId& port_id,
- void* raw_callback);
- // Called when the messaging event has been dispatched with the result of the
- // listeners.
- void OnEventFired(const PortId& port_id,
- v8::Local<v8::Context> context,
- v8::MaybeLocal<v8::Value> result);
- // The associated bindings system. Outlives this object.
- NativeExtensionBindingsSystem* const bindings_system_;
- base::WeakPtrFactory<OneTimeMessageHandler> weak_factory_{this};
- };
- } // namespace extensions
- #endif // EXTENSIONS_RENDERER_ONE_TIME_MESSAGE_HANDLER_H_
|