// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef EXTENSIONS_BROWSER_API_MESSAGING_MESSAGE_SERVICE_H_
#define EXTENSIONS_BROWSER_API_MESSAGING_MESSAGE_SERVICE_H_

#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>

#include "base/compiler_specific.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "extensions/browser/api/messaging/message_port.h"
#include "extensions/browser/api/messaging/native_message_host.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/lazy_context_id.h"
#include "extensions/browser/lazy_context_task_queue.h"
#include "extensions/common/api/messaging/message.h"
#include "extensions/common/api/messaging/port_id.h"
#include "extensions/common/extension_id.h"

class GURL;

namespace content {
class BrowserContext;
}

namespace extensions {

namespace mojom {
enum class ChannelType;
}

class ChannelEndpoint;
class Extension;
class ExtensionHost;
class MessagingDelegate;
struct MessagingEndpoint;
struct PortContext;

// This class manages message and event passing between renderer processes.
// It maintains a list of processes that are listening to events and a set of
// open channels.
//
// Messaging works this way:
// - An extension-owned script context (like a background page or a content
//   script) adds an event listener to the "onConnect" event.
// - Another context calls "runtime.connect()" to open a channel to the
// extension process, or an extension context calls "tabs.connect(tabId)" to
// open a channel to the content scripts for the given tab.  The EMS notifies
// the target process/tab, which then calls the onConnect event in every
// context owned by the connecting extension in that process/tab.
// - Once the channel is established, either side can call postMessage to send
// a message to the opposite side of the channel, which may have multiple
// listeners.
//
// Terminology:
// channel: connection between two ports
// port: One sender or receiver tied to one or more RenderFrameHost instances.
class MessageService : public BrowserContextKeyedAPI,
                       public MessagePort::ChannelDelegate {
 public:
  // A messaging channel. Note that the opening port can be the same as the
  // receiver, if an extension background page wants to talk to its tab (for
  // example).
  struct MessageChannel;

  explicit MessageService(content::BrowserContext* context);

  MessageService(const MessageService&) = delete;
  MessageService& operator=(const MessageService&) = delete;

  ~MessageService() override;

  // BrowserContextKeyedAPI implementation.
  static BrowserContextKeyedAPIFactory<MessageService>* GetFactoryInstance();

  // MessagePort::ChannelDelegate implementation.
  void CloseChannel(const PortId& port_id,
                    const std::string& error_message) override;
  void ClosePort(const PortId& port_id,
                 int process_id,
                 const PortContext& port_context,
                 bool close_channel,
                 const std::string& error_message) override;
  void PostMessage(const PortId& port_id, const Message& message) override;
  void NotifyResponsePending(const PortId& port_id) override;

  // Convenience method to get the MessageService for a browser context.
  static MessageService* Get(content::BrowserContext* context);

  // Given an extension's ID, opens a channel between the given renderer "port"
  // and every listening context owned by that extension. `channel_name` is
  // an optional identifier for use by extension developers. `opener_port` is an
  // optional pre-opened port that should be attached to the opened channel.
  void OpenChannelToExtension(const ChannelEndpoint& source,
                              const PortId& source_port_id,
                              const MessagingEndpoint& source_endpoint,
                              std::unique_ptr<MessagePort> opener_port,
                              const std::string& target_extension_id,
                              const GURL& source_url,
                              mojom::ChannelType channel_type,
                              const std::string& channel_name);

  using ExternalConnectionInfo = mojom::ExternalConnectionInfo;
  void OpenChannelToExtension(
      const ChannelEndpoint& source,
      const PortId& source_port_id,
      const ExternalConnectionInfo& info,
      mojom::ChannelType channel_type,
      const std::string& channel_name,
      mojo::PendingAssociatedRemote<extensions::mojom::MessagePort> port,
      mojo::PendingAssociatedReceiver<extensions::mojom::MessagePortHost>
          port_host);
  void OpenChannelToNativeApp(
      const ChannelEndpoint& source,
      const PortId& source_port_id,
      const std::string& native_app_name,
      mojo::PendingAssociatedRemote<extensions::mojom::MessagePort> port,
      mojo::PendingAssociatedReceiver<extensions::mojom::MessagePortHost>
          port_host);
  void OpenChannelToTab(
      const ChannelEndpoint& source,
      const PortId& source_port_id,
      int tab_id,
      int frame_id,
      const std::string& document_id,
      mojom::ChannelType channel_type,
      const std::string& channel_name,
      mojo::PendingAssociatedRemote<extensions::mojom::MessagePort> port,
      mojo::PendingAssociatedReceiver<extensions::mojom::MessagePortHost>
          port_host);

  // Marks the given port as opened by `port_context` in the render process
  // with id `process_id`.
  void OpenPort(content::RenderProcessHost* process,
                const PortId& port_id,
                const PortContext& port_context);

  // Closes the given port in the given `port_context`. If this was the last
  // context or if `force_close` is true, then the other side is closed as well.
  void ClosePort(content::RenderProcessHost* process,
                 const PortId& port_id,
                 const PortContext& port_context,
                 bool force_close);

  // Notifies the port that one of the receivers of a message indicated that
  // they plan to respond to the message later.
  void NotifyResponsePending(content::RenderProcessHost* process,
                             const PortId& port_id,
                             const PortContext& port_context);

  // Returns the number of open channels for test.
  size_t GetChannelCountForTest() { return channels_.size(); }

  bool HasPendingLazyContextChannelsForExtension(
      const ExtensionId& extension_id) const;

  base::WeakPtr<MessagePort::ChannelDelegate> GetChannelDelegate() {
    return weak_factory_.GetWeakPtr();
  }

 private:
  friend class MockMessageService;
  friend class BrowserContextKeyedAPIFactory<MessageService>;
  struct OpenChannelParams;

  // Same as `OpenChannelToExtension`, but opens a channel to the tab with the
  // given ID.  Messages are restricted to that tab, so if there are multiple
  // tabs in that process, only the targeted tab will receive messages.
  void OpenChannelToTabImpl(
      const ChannelEndpoint& source,
      const PortId& source_port_id,
      int tab_id,
      int frame_id,
      const std::string& document_id,
      const ExtensionId& extension_id,
      mojom::ChannelType channel_type,
      const std::string& channel_name,
      mojo::PendingAssociatedRemote<extensions::mojom::MessagePort> port,
      mojo::PendingAssociatedReceiver<extensions::mojom::MessagePortHost>
          port_host);

  // Creates a MessagePort for the tab with the given `web_contents`.
  // Returns nullptr if the tab is not available.
  std::unique_ptr<MessagePort> CreateReceiverForTab(
      const ExtensionId& extension_id,
      const PortId& receiver_port_id,
      content::WebContents* receiver_contents,
      int receiver_frame_id,
      const std::string& receiver_document_id);

  void OpenChannelToNativeAppImpl(
      const ChannelEndpoint& source,
      const PortId& source_port_id,
      const std::string& native_app_name,
      mojo::PendingAssociatedRemote<extensions::mojom::MessagePort> port,
      mojo::PendingAssociatedReceiver<extensions::mojom::MessagePortHost>
          port_host);
  void OpenPortImpl(const PortId& port_id,
                    int process_id,
                    const PortContext& port_context);

  // A map of channel ID to its channel object.
  using MessageChannelMap =
      std::map<ChannelId, std::unique_ptr<MessageChannel>>;

  using PendingMessage = std::pair<PortId, Message>;
  using PendingMessagesQueue = std::vector<PendingMessage>;
  // A set of channel IDs waiting to complete opening, and any pending messages
  // queued to be sent on those channels.
  using PendingChannelMap = std::map<ChannelId, PendingMessagesQueue>;

  // A map of channel ID to information about the extension that is waiting
  // for that channel to open. Used for lazy background pages or Service
  // Workers.
  using PendingLazyContextChannelMap = std::map<ChannelId, LazyContextId>;

  // Common implementation for opening a channel configured by `params`.
  //
  // `target_extension` will be non-null if |params->target_extension_id| is
  // non-empty, that is, if the target is an extension, it must exist.
  //
  // `did_enqueue` will be true if the channel opening was delayed while
  // waiting for an event page to start, false otherwise.
  void OpenChannelImpl(content::BrowserContext* browser_context,
                       std::unique_ptr<OpenChannelParams> params,
                       const Extension* target_extension,
                       bool did_enqueue);

  void ClosePortImpl(const PortId& port_id,
                     int process_id,
                     int routing_id,
                     int worker_thread_id,
                     bool force_close,
                     const std::string& error_message);

  void CloseChannelImpl(MessageChannelMap::iterator channel_iter,
                        const PortId& port_id,
                        const std::string& error_message,
                        bool notify_other_port);

  // Have MessageService take ownership of `channel`, and remove any pending
  // channels with the same id.
  void AddChannel(std::unique_ptr<MessageChannel> channel,
                  const PortId& receiver_port_id);

  // If the channel is being opened from an incognito tab the user must allow
  // the connection.
  void OnOpenChannelAllowed(std::unique_ptr<OpenChannelParams> params,
                            bool allowed);

  // Enqueues a message on a pending channel.
  void EnqueuePendingMessage(const PortId& port_id,
                             const ChannelId& channel_id,
                             const Message& message);

  // Enqueues a message on a channel pending on a lazy background page load.
  void EnqueuePendingMessageForLazyBackgroundLoad(const PortId& port_id,
                                                  const ChannelId& channel_id,
                                                  const Message& message);

  // Immediately sends a message to the given port.
  void DispatchMessage(const PortId& port_id,
                       MessageChannel* channel,
                       const Message& message);

  // Potentially registers a pending task with lazy context task queue
  // to open a channel. Returns true if a task was queued.
  // Takes ownership of `params` if true is returned.
  bool MaybeAddPendingLazyContextOpenChannelTask(
      content::BrowserContext* context,
      const Extension* extension,
      std::unique_ptr<OpenChannelParams>* params,
      const PendingMessagesQueue& pending_messages);

  // Callbacks for background task queue tasks. The queue passes in an
  // ExtensionHost to its task callbacks, though some of our callbacks don't
  // use that argument.
  void PendingLazyContextOpenChannel(
      std::unique_ptr<OpenChannelParams> params,
      const base::UnguessableToken& open_channel_wakeup_context_tracking_id,
      std::unique_ptr<LazyContextTaskQueue::ContextInfo> context_info);
  void PendingLazyContextClosePort(
      const PortId& port_id,
      int process_id,
      int routing_id,
      int worker_thread_id,
      bool force_close,
      const std::string& error_message,
      std::unique_ptr<LazyContextTaskQueue::ContextInfo> context_info) {
    if (context_info) {
      ClosePortImpl(port_id, process_id, routing_id, worker_thread_id,
                    force_close, error_message);
    }
  }
  void PendingLazyContextPostMessage(
      const PortId& port_id,
      const Message& message,
      std::unique_ptr<LazyContextTaskQueue::ContextInfo> context_info) {
    if (context_info) {
      PostMessage(port_id, message);
    }
  }

  void DispatchPendingMessages(const PendingMessagesQueue& queue,
                               const ChannelId& channel_id);

  // BrowserContextKeyedAPI implementation.
  static const char* service_name() { return "MessageService"; }
  static const bool kServiceRedirectedInIncognito = true;
  static const bool kServiceIsCreatedWithBrowserContext = false;
  static const bool kServiceIsNULLWhileTesting = true;

  const raw_ptr<content::BrowserContext> context_;

  // Delegate for embedder-specific messaging, e.g. for Chrome tabs.
  // Owned by the ExtensionsAPIClient and guaranteed to outlive `this`.
  raw_ptr<MessagingDelegate> messaging_delegate_;

  MessageChannelMap channels_;
  // A set of channel IDs waiting for user permission to cross the border
  // between an incognito page and an app or extension, and any pending messages
  // queued to be sent on those channels.
  PendingChannelMap pending_incognito_channels_;
  PendingLazyContextChannelMap pending_lazy_context_channels_;

  base::WeakPtrFactory<MessageService> weak_factory_{this};
};

}  // namespace extensions

#endif  // EXTENSIONS_BROWSER_API_MESSAGING_MESSAGE_SERVICE_H_
