Skip to main content

bitwarden_ipc/
endpoint.rs

1use serde::{Deserialize, Serialize};
2
3/// Identifies a host endpoint, one that manages connections for other endpoints.
4///
5/// Host endpoints can be addressed relationally (when the sender has a direct connection
6/// and there is only one from their perspective) or by a specific transport-assigned ID
7/// (when distinguishing between multiple instances).
8#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
9#[bitwarden_ffi::wasm_record]
10pub enum HostId {
11    /// The sender's own instance of this endpoint type. Used when there is exactly one
12    /// from the sender's perspective (e.g., a web tab addressing its browser background).
13    Own,
14    /// A specific instance identified by a transport-assigned numeric value
15    /// (e.g., native messaging client ID).
16    Id(i32),
17}
18
19/// IPC destination/source endpoint for SDK clients.
20///
21/// Endpoints are categorized by their role in the connection topology:
22/// - **Host endpoints** ([`HostId`]): Connection hubs that can be addressed relationally or
23///   specifically. ([`BrowserBackground`](Endpoint::BrowserBackground), [`Cli`](Endpoint::Cli))
24/// - **Leaf endpoints**: Addressed by transport-assigned IDs. ([`Web`](Endpoint::Web),
25///   [`BrowserForeground`](Endpoint::BrowserForeground))
26/// - **Singleton endpoints**: Exactly one instance globally, no ID needed.
27///   ([`DesktopMain`](Endpoint::DesktopMain), [`DesktopRenderer`](Endpoint::DesktopRenderer))
28#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
29#[bitwarden_ffi::wasm_record]
30pub enum Endpoint {
31    /// A web endpoint identified by a Chrome tab ID (for routing via
32    /// `chrome.tabs.sendMessage`) and a document ID (for identity validation).
33    /// The document ID invalidates on navigation, allowing the browser background
34    /// to reject delivery if the page changed since the message was addressed.
35    Web {
36        /// Chrome tab ID used for routing messages to the correct tab.
37        tab_id: i32,
38        /// Document ID (`sender.documentId`) identifying a specific document instance.
39        document_id: String,
40    },
41    /// Browser foreground endpoint (popup, sidebar, or extension page) identified by a
42    /// transport-assigned numeric ID.
43    BrowserForeground {
44        /// Transport-assigned identifier for a browser foreground instance.
45        id: i32,
46    },
47    /// Browser background endpoint (service worker/background context).
48    BrowserBackground {
49        /// Host identifier for addressing this endpoint.
50        id: HostId,
51    },
52    /// CLI endpoint. Each CLI invocation is its own process, so instances are
53    /// distinguished by a host identifier.
54    Cli {
55        /// Host identifier for addressing this endpoint.
56        id: HostId,
57    },
58    /// Desktop renderer endpoint (singleton).
59    DesktopRenderer,
60    /// Desktop main-process endpoint (singleton).
61    DesktopMain,
62}
63
64/// Describes the source of an incoming IPC message with per-variant metadata.
65///
66/// `Source` mirrors [`Endpoint`] but carries additional context about the sender
67/// that the application layer needs for security decisions (e.g., checking `origin`
68/// for web sources). Use [`From<Source> for Endpoint`] to convert a source into an
69/// addressable endpoint (dropping the metadata).
70#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
71#[bitwarden_ffi::wasm_record]
72pub enum Source {
73    /// A web source identified by tab ID and document ID, with the origin of the sending page.
74    Web {
75        /// Chrome tab ID used for routing messages back to this tab.
76        tab_id: i32,
77        /// Document ID (`sender.documentId`) identifying the specific document instance.
78        document_id: String,
79        /// The origin of the web page (e.g., `"https://vault.bitwarden.com"`).
80        origin: String,
81    },
82    /// Browser foreground source (popup, sidebar, or extension page).
83    BrowserForeground {
84        /// Transport-assigned identifier for the browser foreground instance.
85        id: i32,
86    },
87    /// Browser background source (service worker/background context).
88    BrowserBackground {
89        /// Host identifier for this endpoint.
90        id: HostId,
91    },
92    /// CLI source, identified by a host identifier.
93    Cli {
94        /// Host identifier for this endpoint.
95        id: HostId,
96    },
97    /// Desktop renderer source (singleton).
98    DesktopRenderer,
99    /// Desktop main-process source (singleton).
100    DesktopMain,
101}
102
103impl Source {
104    /// Convert this source into its corresponding [`Endpoint`], dropping any
105    /// source-specific metadata (such as `origin`).
106    pub fn to_endpoint(&self) -> Endpoint {
107        Endpoint::from(self.clone())
108    }
109}
110
111impl From<Source> for Endpoint {
112    fn from(source: Source) -> Self {
113        match source {
114            Source::Web {
115                tab_id,
116                document_id,
117                ..
118            } => Endpoint::Web {
119                tab_id,
120                document_id,
121            },
122            Source::BrowserForeground { id } => Endpoint::BrowserForeground { id },
123            Source::BrowserBackground { id } => Endpoint::BrowserBackground { id },
124            Source::Cli { id } => Endpoint::Cli { id },
125            Source::DesktopRenderer => Endpoint::DesktopRenderer,
126            Source::DesktopMain => Endpoint::DesktopMain,
127        }
128    }
129}