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

module extensions.mojom;

import "mojo/public/mojom/base/big_buffer.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "mojo/public/mojom/base/values.mojom";
import "third_party/blink/public/mojom/messaging/cloneable_message.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";

// IPC messages will fail at > 128 MiB. Restrict extension messages to 64 MiB.
// A 64 MiB JSON serialized object is scary enough as it is.
// TODO(crbug.com/40321352): The 64 MiB limit also applies to structured clone
// messages. Can we unrestrict that since it uses
// `blink.mojom.CloneableMessage` (which contains `mojo_base.mojom.BigBuffer`
// that has shared memory benefits for large messages)?
const uint64 kMaxMessageBytes = 67108864;  // 64 * 1024 * 1024

// The serialization format of the message.
// NOTE: To obtain this for message sending purposes use
// `messaging_util::GetSerializationFormat()`.
enum SerializationFormat {
  // Serialized using the structured clone algorithm. Used for
  // standard extension messaging channels (`ChannelType::kSendMessage`,
  // `ChannelType::kConnect`) to support richer data types.
  kStructuredClone,
  // Serialized using JSON. Used for `ChannelType::kNative` messaging (which
  // requires JSON) and legacy methods (`ChannelType::kSendRequest`).
  kJson,
};

// The type of messaging channel.
enum ChannelType {
  // A message channel associated with `runtime.sendMessage()` or
  // `tabs.sendMessage()`.
  kSendMessage,
  // A message channel associated with `extension.sendRequest()`.
  kSendRequest,
  // A longer-lived message channel associated with `runtime.connect()`
  // or `tabs.connect()`.
  kConnect,
  // A native message channel. Note that unlike above, both one-time and
  // long-lived native message channels use the same type (because they don't
  // have associated channel names).
  kNative,
};

// Type of the messaging source or destination - i.e., the type of the
// component which talks to a messaging channel.
enum MessagingEndpointType {
  // An extension.
  kExtension,
  // A web page or a hosted app.
  kWebPage,
  // A content script.
  kContentScript,
  // A user script.
  kUserScript,
  // A native application.
  kNativeApp,
};

// Definition of a port. This struct will eventually go away when all
// legacy IPC messages have been removed to use the targeted
// MessagePort/MessagePortHost below.
struct PortId {
  mojo_base.mojom.UnguessableToken context_id;
  int32 port_number;
  bool is_opener;
  SerializationFormat serialization_format;
};

// Definition of an endpoint.
struct MessagingEndpoint {
  MessagingEndpointType type;
  string? extension_id;
  string? native_app_name;
};

// Definition of the tab that is being connected.
struct TabConnectionInfo {
  mojo_base.mojom.DictionaryValue tab;
  int32 frame_id;
  string document_id;
  string document_lifecycle;
};

// Connection information.
struct ExternalConnectionInfo {
  MessagingEndpoint source_endpoint;
  string target_id;
  url.mojom.Url source_url;
  url.mojom.Origin? source_origin;
  int32 guest_process_id;
  int32 guest_render_frame_routing_id;
};

// The data payload of a message.
union MessageData {
  string json;
  blink.mojom.CloneableMessage structured_message;
};

// A message that is serialized across the channel.
struct Message {
  // The data payload of the message.
  MessageData data;
  // Whether the message was sent with a user gesture. This is determined by
  // the sender's context.
  bool user_gesture;
  // Whether the message originated from a privileged extension context
  // (specifically, `mojom::ContextType::kPrivilegedExtension`). This typically
  // corresponds to the extension's background context (page or service worker).
  bool from_privileged_context;
};

// The renderer interface to a message port.
interface MessagePort {
  // Dispatch the Port.onDisconnect event for message channels.
  DispatchDisconnect(string error);

  // Deliver a message sent with MessagePortHost.PostMessage.
  DeliverMessage(Message message);
};

// The browser interface to a message port.
interface MessagePortHost {
  // Closes the messaging port from the renderer to the browser. `close_channel`
  // indicates that there will be no more responders so the browser should close
  // the channel.
  // `error_message`, if present, is if the port was closed due to an error in
  // the message listener for this port. It's the error message provided by the
  // message listener explicitly or it's a static generic error message if an
  // error message couldn't be found, but an error was thrown. The error message
  // is ultimately passed along to the message opener in a different javascript
  // context, and possibly in another renderer via the browser. It is so that
  // the opener can react to the error (for retries, debugging, etc.)
  ClosePort(bool close_channel, string? error_message);

  // Send a message to an extension process.
  PostMessage(Message message);

  // Send a message to tell the browser that one of the listeners for a message
  // indicated they are intending to reply later.
  ResponsePending();
};
