Skip to main content

browser_protocol/fedcm/
mod.rs

1//! This domain allows interacting with the FedCM dialog.
2
3
4use serde::{Serialize, Deserialize};
5use serde_json::Value as JsonValue;
6use std::borrow::Cow;
7
8/// Whether this is a sign-up or sign-in action for this account, i.e.
9/// whether this account has ever been used to sign in to this RP before.
10
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
12pub enum LoginState {
13    #[default]
14    #[serde(rename = "SignIn")]
15    SignIn,
16    #[serde(rename = "SignUp")]
17    SignUp,
18}
19
20/// The types of FedCM dialogs.
21
22#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
23pub enum DialogType {
24    #[default]
25    #[serde(rename = "AccountChooser")]
26    AccountChooser,
27    #[serde(rename = "AutoReauthn")]
28    AutoReauthn,
29    #[serde(rename = "ConfirmIdpLogin")]
30    ConfirmIdpLogin,
31    #[serde(rename = "Error")]
32    Error,
33}
34
35/// The buttons on the FedCM dialog.
36
37#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
38pub enum DialogButton {
39    #[default]
40    #[serde(rename = "ConfirmIdpLoginContinue")]
41    ConfirmIdpLoginContinue,
42    #[serde(rename = "ErrorGotIt")]
43    ErrorGotIt,
44    #[serde(rename = "ErrorMoreDetails")]
45    ErrorMoreDetails,
46}
47
48/// The URLs that each account has
49
50#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
51pub enum AccountUrlType {
52    #[default]
53    #[serde(rename = "TermsOfService")]
54    TermsOfService,
55    #[serde(rename = "PrivacyPolicy")]
56    PrivacyPolicy,
57}
58
59/// Corresponds to IdentityRequestAccount
60
61#[derive(Debug, Clone, Serialize, Deserialize, Default)]
62#[serde(rename_all = "camelCase")]
63pub struct Account<'a> {
64    accountId: Cow<'a, str>,
65    email: Cow<'a, str>,
66    name: Cow<'a, str>,
67    givenName: Cow<'a, str>,
68    pictureUrl: Cow<'a, str>,
69    idpConfigUrl: Cow<'a, str>,
70    idpLoginUrl: Cow<'a, str>,
71    loginState: LoginState,
72    /// These two are only set if the loginState is signUp
73    #[serde(skip_serializing_if = "Option::is_none")]
74    termsOfServiceUrl: Option<Cow<'a, str>>,
75    #[serde(skip_serializing_if = "Option::is_none")]
76    privacyPolicyUrl: Option<Cow<'a, str>>,
77}
78
79impl<'a> Account<'a> {
80    pub fn builder(accountId: impl Into<Cow<'a, str>>, email: impl Into<Cow<'a, str>>, name: impl Into<Cow<'a, str>>, givenName: impl Into<Cow<'a, str>>, pictureUrl: impl Into<Cow<'a, str>>, idpConfigUrl: impl Into<Cow<'a, str>>, idpLoginUrl: impl Into<Cow<'a, str>>, loginState: LoginState) -> AccountBuilder<'a> {
81        AccountBuilder {
82            accountId: accountId.into(),
83            email: email.into(),
84            name: name.into(),
85            givenName: givenName.into(),
86            pictureUrl: pictureUrl.into(),
87            idpConfigUrl: idpConfigUrl.into(),
88            idpLoginUrl: idpLoginUrl.into(),
89            loginState: loginState,
90            termsOfServiceUrl: None,
91            privacyPolicyUrl: None,
92        }
93    }
94    pub fn accountId(&self) -> &str { self.accountId.as_ref() }
95    pub fn email(&self) -> &str { self.email.as_ref() }
96    pub fn name(&self) -> &str { self.name.as_ref() }
97    pub fn givenName(&self) -> &str { self.givenName.as_ref() }
98    pub fn pictureUrl(&self) -> &str { self.pictureUrl.as_ref() }
99    pub fn idpConfigUrl(&self) -> &str { self.idpConfigUrl.as_ref() }
100    pub fn idpLoginUrl(&self) -> &str { self.idpLoginUrl.as_ref() }
101    pub fn loginState(&self) -> &LoginState { &self.loginState }
102    pub fn termsOfServiceUrl(&self) -> Option<&str> { self.termsOfServiceUrl.as_deref() }
103    pub fn privacyPolicyUrl(&self) -> Option<&str> { self.privacyPolicyUrl.as_deref() }
104}
105
106
107pub struct AccountBuilder<'a> {
108    accountId: Cow<'a, str>,
109    email: Cow<'a, str>,
110    name: Cow<'a, str>,
111    givenName: Cow<'a, str>,
112    pictureUrl: Cow<'a, str>,
113    idpConfigUrl: Cow<'a, str>,
114    idpLoginUrl: Cow<'a, str>,
115    loginState: LoginState,
116    termsOfServiceUrl: Option<Cow<'a, str>>,
117    privacyPolicyUrl: Option<Cow<'a, str>>,
118}
119
120impl<'a> AccountBuilder<'a> {
121    /// These two are only set if the loginState is signUp
122    pub fn termsOfServiceUrl(mut self, termsOfServiceUrl: impl Into<Cow<'a, str>>) -> Self { self.termsOfServiceUrl = Some(termsOfServiceUrl.into()); self }
123    pub fn privacyPolicyUrl(mut self, privacyPolicyUrl: impl Into<Cow<'a, str>>) -> Self { self.privacyPolicyUrl = Some(privacyPolicyUrl.into()); self }
124    pub fn build(self) -> Account<'a> {
125        Account {
126            accountId: self.accountId,
127            email: self.email,
128            name: self.name,
129            givenName: self.givenName,
130            pictureUrl: self.pictureUrl,
131            idpConfigUrl: self.idpConfigUrl,
132            idpLoginUrl: self.idpLoginUrl,
133            loginState: self.loginState,
134            termsOfServiceUrl: self.termsOfServiceUrl,
135            privacyPolicyUrl: self.privacyPolicyUrl,
136        }
137    }
138}
139
140
141#[derive(Debug, Clone, Serialize, Deserialize, Default)]
142#[serde(rename_all = "camelCase")]
143pub struct EnableParams {
144    /// Allows callers to disable the promise rejection delay that would
145    /// normally happen, if this is unimportant to what's being tested.
146    /// (step 4 of https://fedidcg.github.io/FedCM/#browser-api-rp-sign-in)
147    #[serde(skip_serializing_if = "Option::is_none")]
148    disableRejectionDelay: Option<bool>,
149}
150
151impl EnableParams {
152    pub fn builder() -> EnableParamsBuilder {
153        EnableParamsBuilder {
154            disableRejectionDelay: None,
155        }
156    }
157    pub fn disableRejectionDelay(&self) -> Option<bool> { self.disableRejectionDelay }
158}
159
160#[derive(Default)]
161pub struct EnableParamsBuilder {
162    disableRejectionDelay: Option<bool>,
163}
164
165impl EnableParamsBuilder {
166    /// Allows callers to disable the promise rejection delay that would
167    /// normally happen, if this is unimportant to what's being tested.
168    /// (step 4 of https://fedidcg.github.io/FedCM/#browser-api-rp-sign-in)
169    pub fn disableRejectionDelay(mut self, disableRejectionDelay: bool) -> Self { self.disableRejectionDelay = Some(disableRejectionDelay); self }
170    pub fn build(self) -> EnableParams {
171        EnableParams {
172            disableRejectionDelay: self.disableRejectionDelay,
173        }
174    }
175}
176
177impl EnableParams { pub const METHOD: &'static str = "FedCm.enable"; }
178
179impl<'a> crate::CdpCommand<'a> for EnableParams {
180    const METHOD: &'static str = "FedCm.enable";
181    type Response = crate::EmptyReturns;
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize, Default)]
185pub struct DisableParams {}
186
187impl DisableParams { pub const METHOD: &'static str = "FedCm.disable"; }
188
189impl<'a> crate::CdpCommand<'a> for DisableParams {
190    const METHOD: &'static str = "FedCm.disable";
191    type Response = crate::EmptyReturns;
192}
193
194
195#[derive(Debug, Clone, Serialize, Deserialize, Default)]
196#[serde(rename_all = "camelCase")]
197pub struct SelectAccountParams<'a> {
198    dialogId: Cow<'a, str>,
199    accountIndex: u64,
200}
201
202impl<'a> SelectAccountParams<'a> {
203    pub fn builder(dialogId: impl Into<Cow<'a, str>>, accountIndex: u64) -> SelectAccountParamsBuilder<'a> {
204        SelectAccountParamsBuilder {
205            dialogId: dialogId.into(),
206            accountIndex: accountIndex,
207        }
208    }
209    pub fn dialogId(&self) -> &str { self.dialogId.as_ref() }
210    pub fn accountIndex(&self) -> u64 { self.accountIndex }
211}
212
213
214pub struct SelectAccountParamsBuilder<'a> {
215    dialogId: Cow<'a, str>,
216    accountIndex: u64,
217}
218
219impl<'a> SelectAccountParamsBuilder<'a> {
220    pub fn build(self) -> SelectAccountParams<'a> {
221        SelectAccountParams {
222            dialogId: self.dialogId,
223            accountIndex: self.accountIndex,
224        }
225    }
226}
227
228impl<'a> SelectAccountParams<'a> { pub const METHOD: &'static str = "FedCm.selectAccount"; }
229
230impl<'a> crate::CdpCommand<'a> for SelectAccountParams<'a> {
231    const METHOD: &'static str = "FedCm.selectAccount";
232    type Response = crate::EmptyReturns;
233}
234
235
236#[derive(Debug, Clone, Serialize, Deserialize, Default)]
237#[serde(rename_all = "camelCase")]
238pub struct ClickDialogButtonParams<'a> {
239    dialogId: Cow<'a, str>,
240    dialogButton: DialogButton,
241}
242
243impl<'a> ClickDialogButtonParams<'a> {
244    pub fn builder(dialogId: impl Into<Cow<'a, str>>, dialogButton: DialogButton) -> ClickDialogButtonParamsBuilder<'a> {
245        ClickDialogButtonParamsBuilder {
246            dialogId: dialogId.into(),
247            dialogButton: dialogButton,
248        }
249    }
250    pub fn dialogId(&self) -> &str { self.dialogId.as_ref() }
251    pub fn dialogButton(&self) -> &DialogButton { &self.dialogButton }
252}
253
254
255pub struct ClickDialogButtonParamsBuilder<'a> {
256    dialogId: Cow<'a, str>,
257    dialogButton: DialogButton,
258}
259
260impl<'a> ClickDialogButtonParamsBuilder<'a> {
261    pub fn build(self) -> ClickDialogButtonParams<'a> {
262        ClickDialogButtonParams {
263            dialogId: self.dialogId,
264            dialogButton: self.dialogButton,
265        }
266    }
267}
268
269impl<'a> ClickDialogButtonParams<'a> { pub const METHOD: &'static str = "FedCm.clickDialogButton"; }
270
271impl<'a> crate::CdpCommand<'a> for ClickDialogButtonParams<'a> {
272    const METHOD: &'static str = "FedCm.clickDialogButton";
273    type Response = crate::EmptyReturns;
274}
275
276
277#[derive(Debug, Clone, Serialize, Deserialize, Default)]
278#[serde(rename_all = "camelCase")]
279pub struct OpenUrlParams<'a> {
280    dialogId: Cow<'a, str>,
281    accountIndex: u64,
282    accountUrlType: AccountUrlType,
283}
284
285impl<'a> OpenUrlParams<'a> {
286    pub fn builder(dialogId: impl Into<Cow<'a, str>>, accountIndex: u64, accountUrlType: AccountUrlType) -> OpenUrlParamsBuilder<'a> {
287        OpenUrlParamsBuilder {
288            dialogId: dialogId.into(),
289            accountIndex: accountIndex,
290            accountUrlType: accountUrlType,
291        }
292    }
293    pub fn dialogId(&self) -> &str { self.dialogId.as_ref() }
294    pub fn accountIndex(&self) -> u64 { self.accountIndex }
295    pub fn accountUrlType(&self) -> &AccountUrlType { &self.accountUrlType }
296}
297
298
299pub struct OpenUrlParamsBuilder<'a> {
300    dialogId: Cow<'a, str>,
301    accountIndex: u64,
302    accountUrlType: AccountUrlType,
303}
304
305impl<'a> OpenUrlParamsBuilder<'a> {
306    pub fn build(self) -> OpenUrlParams<'a> {
307        OpenUrlParams {
308            dialogId: self.dialogId,
309            accountIndex: self.accountIndex,
310            accountUrlType: self.accountUrlType,
311        }
312    }
313}
314
315impl<'a> OpenUrlParams<'a> { pub const METHOD: &'static str = "FedCm.openUrl"; }
316
317impl<'a> crate::CdpCommand<'a> for OpenUrlParams<'a> {
318    const METHOD: &'static str = "FedCm.openUrl";
319    type Response = crate::EmptyReturns;
320}
321
322
323#[derive(Debug, Clone, Serialize, Deserialize, Default)]
324#[serde(rename_all = "camelCase")]
325pub struct DismissDialogParams<'a> {
326    dialogId: Cow<'a, str>,
327    #[serde(skip_serializing_if = "Option::is_none")]
328    triggerCooldown: Option<bool>,
329}
330
331impl<'a> DismissDialogParams<'a> {
332    pub fn builder(dialogId: impl Into<Cow<'a, str>>) -> DismissDialogParamsBuilder<'a> {
333        DismissDialogParamsBuilder {
334            dialogId: dialogId.into(),
335            triggerCooldown: None,
336        }
337    }
338    pub fn dialogId(&self) -> &str { self.dialogId.as_ref() }
339    pub fn triggerCooldown(&self) -> Option<bool> { self.triggerCooldown }
340}
341
342
343pub struct DismissDialogParamsBuilder<'a> {
344    dialogId: Cow<'a, str>,
345    triggerCooldown: Option<bool>,
346}
347
348impl<'a> DismissDialogParamsBuilder<'a> {
349    pub fn triggerCooldown(mut self, triggerCooldown: bool) -> Self { self.triggerCooldown = Some(triggerCooldown); self }
350    pub fn build(self) -> DismissDialogParams<'a> {
351        DismissDialogParams {
352            dialogId: self.dialogId,
353            triggerCooldown: self.triggerCooldown,
354        }
355    }
356}
357
358impl<'a> DismissDialogParams<'a> { pub const METHOD: &'static str = "FedCm.dismissDialog"; }
359
360impl<'a> crate::CdpCommand<'a> for DismissDialogParams<'a> {
361    const METHOD: &'static str = "FedCm.dismissDialog";
362    type Response = crate::EmptyReturns;
363}
364
365#[derive(Debug, Clone, Serialize, Deserialize, Default)]
366pub struct ResetCooldownParams {}
367
368impl ResetCooldownParams { pub const METHOD: &'static str = "FedCm.resetCooldown"; }
369
370impl<'a> crate::CdpCommand<'a> for ResetCooldownParams {
371    const METHOD: &'static str = "FedCm.resetCooldown";
372    type Response = crate::EmptyReturns;
373}