Skip to main content

browser_protocol/pwa/
mod.rs

1//! This domain allows interacting with the browser to control PWAs.
2
3
4use serde::{Serialize, Deserialize};
5use serde_json::Value as JsonValue;
6use std::borrow::Cow;
7
8/// The following types are the replica of
9/// https://crsrc.org/c/chrome/browser/web_applications/proto/web_app_os_integration_state.proto;drc=9910d3be894c8f142c977ba1023f30a656bc13fc;l=67
10
11#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12#[serde(rename_all = "camelCase")]
13pub struct FileHandlerAccept<'a> {
14    /// New name of the mimetype according to
15    /// https://www.iana.org/assignments/media-types/media-types.xhtml
16    mediaType: Cow<'a, str>,
17    fileExtensions: Vec<Cow<'a, str>>,
18}
19
20impl<'a> FileHandlerAccept<'a> {
21    pub fn builder(mediaType: impl Into<Cow<'a, str>>, fileExtensions: Vec<Cow<'a, str>>) -> FileHandlerAcceptBuilder<'a> {
22        FileHandlerAcceptBuilder {
23            mediaType: mediaType.into(),
24            fileExtensions: fileExtensions,
25        }
26    }
27    pub fn mediaType(&self) -> &str { self.mediaType.as_ref() }
28    pub fn fileExtensions(&self) -> &[Cow<'a, str>] { &self.fileExtensions }
29}
30
31
32pub struct FileHandlerAcceptBuilder<'a> {
33    mediaType: Cow<'a, str>,
34    fileExtensions: Vec<Cow<'a, str>>,
35}
36
37impl<'a> FileHandlerAcceptBuilder<'a> {
38    pub fn build(self) -> FileHandlerAccept<'a> {
39        FileHandlerAccept {
40            mediaType: self.mediaType,
41            fileExtensions: self.fileExtensions,
42        }
43    }
44}
45
46
47#[derive(Debug, Clone, Serialize, Deserialize, Default)]
48#[serde(rename_all = "camelCase")]
49pub struct FileHandler<'a> {
50    action: Cow<'a, str>,
51    accepts: Vec<FileHandlerAccept<'a>>,
52    displayName: Cow<'a, str>,
53}
54
55impl<'a> FileHandler<'a> {
56    pub fn builder(action: impl Into<Cow<'a, str>>, accepts: Vec<FileHandlerAccept<'a>>, displayName: impl Into<Cow<'a, str>>) -> FileHandlerBuilder<'a> {
57        FileHandlerBuilder {
58            action: action.into(),
59            accepts: accepts,
60            displayName: displayName.into(),
61        }
62    }
63    pub fn action(&self) -> &str { self.action.as_ref() }
64    pub fn accepts(&self) -> &[FileHandlerAccept<'a>] { &self.accepts }
65    pub fn displayName(&self) -> &str { self.displayName.as_ref() }
66}
67
68
69pub struct FileHandlerBuilder<'a> {
70    action: Cow<'a, str>,
71    accepts: Vec<FileHandlerAccept<'a>>,
72    displayName: Cow<'a, str>,
73}
74
75impl<'a> FileHandlerBuilder<'a> {
76    pub fn build(self) -> FileHandler<'a> {
77        FileHandler {
78            action: self.action,
79            accepts: self.accepts,
80            displayName: self.displayName,
81        }
82    }
83}
84
85/// If user prefers opening the app in browser or an app window.
86
87#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
88pub enum DisplayMode {
89    #[default]
90    #[serde(rename = "standalone")]
91    Standalone,
92    #[serde(rename = "browser")]
93    Browser,
94}
95
96/// Returns the following OS state for the given manifest id.
97
98#[derive(Debug, Clone, Serialize, Deserialize, Default)]
99#[serde(rename_all = "camelCase")]
100pub struct GetOsAppStateParams<'a> {
101    /// The id from the webapp's manifest file, commonly it's the url of the
102    /// site installing the webapp. See
103    /// https://web.dev/learn/pwa/web-app-manifest.
104    manifestId: Cow<'a, str>,
105}
106
107impl<'a> GetOsAppStateParams<'a> {
108    pub fn builder(manifestId: impl Into<Cow<'a, str>>) -> GetOsAppStateParamsBuilder<'a> {
109        GetOsAppStateParamsBuilder {
110            manifestId: manifestId.into(),
111        }
112    }
113    pub fn manifestId(&self) -> &str { self.manifestId.as_ref() }
114}
115
116
117pub struct GetOsAppStateParamsBuilder<'a> {
118    manifestId: Cow<'a, str>,
119}
120
121impl<'a> GetOsAppStateParamsBuilder<'a> {
122    pub fn build(self) -> GetOsAppStateParams<'a> {
123        GetOsAppStateParams {
124            manifestId: self.manifestId,
125        }
126    }
127}
128
129/// Returns the following OS state for the given manifest id.
130
131#[derive(Debug, Clone, Serialize, Deserialize, Default)]
132#[serde(rename_all = "camelCase")]
133pub struct GetOsAppStateReturns<'a> {
134    badgeCount: u64,
135    fileHandlers: Vec<FileHandler<'a>>,
136}
137
138impl<'a> GetOsAppStateReturns<'a> {
139    pub fn builder(badgeCount: u64, fileHandlers: Vec<FileHandler<'a>>) -> GetOsAppStateReturnsBuilder<'a> {
140        GetOsAppStateReturnsBuilder {
141            badgeCount: badgeCount,
142            fileHandlers: fileHandlers,
143        }
144    }
145    pub fn badgeCount(&self) -> u64 { self.badgeCount }
146    pub fn fileHandlers(&self) -> &[FileHandler<'a>] { &self.fileHandlers }
147}
148
149
150pub struct GetOsAppStateReturnsBuilder<'a> {
151    badgeCount: u64,
152    fileHandlers: Vec<FileHandler<'a>>,
153}
154
155impl<'a> GetOsAppStateReturnsBuilder<'a> {
156    pub fn build(self) -> GetOsAppStateReturns<'a> {
157        GetOsAppStateReturns {
158            badgeCount: self.badgeCount,
159            fileHandlers: self.fileHandlers,
160        }
161    }
162}
163
164impl<'a> GetOsAppStateParams<'a> { pub const METHOD: &'static str = "PWA.getOsAppState"; }
165
166impl<'a> crate::CdpCommand<'a> for GetOsAppStateParams<'a> {
167    const METHOD: &'static str = "PWA.getOsAppState";
168    type Response = GetOsAppStateReturns<'a>;
169}
170
171/// Installs the given manifest identity, optionally using the given installUrlOrBundleUrl
172/// 
173/// IWA-specific install description:
174/// manifestId corresponds to isolated-app:// + web_package::SignedWebBundleId
175/// 
176/// File installation mode:
177/// The installUrlOrBundleUrl can be either file:// or http(s):// pointing
178/// to a signed web bundle (.swbn). In this case SignedWebBundleId must correspond to
179/// The .swbn file's signing key.
180/// 
181/// Dev proxy installation mode:
182/// installUrlOrBundleUrl must be http(s):// that serves dev mode IWA.
183/// web_package::SignedWebBundleId must be of type dev proxy.
184/// 
185/// The advantage of dev proxy mode is that all changes to IWA
186/// automatically will be reflected in the running app without
187/// reinstallation.
188/// 
189/// To generate bundle id for proxy mode:
190/// 1. Generate 32 random bytes.
191/// 2. Add a specific suffix at the end following the documentation
192/// https://github.com/WICG/isolated-web-apps/blob/main/Scheme.md#suffix
193/// 3. Encode the entire sequence using Base32 without padding.
194/// 
195/// If Chrome is not in IWA dev
196/// mode, the installation will fail, regardless of the state of the allowlist.
197
198#[derive(Debug, Clone, Serialize, Deserialize, Default)]
199#[serde(rename_all = "camelCase")]
200pub struct InstallParams<'a> {
201    manifestId: Cow<'a, str>,
202    /// The location of the app or bundle overriding the one derived from the
203    /// manifestId.
204    #[serde(skip_serializing_if = "Option::is_none")]
205    installUrlOrBundleUrl: Option<Cow<'a, str>>,
206}
207
208impl<'a> InstallParams<'a> {
209    pub fn builder(manifestId: impl Into<Cow<'a, str>>) -> InstallParamsBuilder<'a> {
210        InstallParamsBuilder {
211            manifestId: manifestId.into(),
212            installUrlOrBundleUrl: None,
213        }
214    }
215    pub fn manifestId(&self) -> &str { self.manifestId.as_ref() }
216    pub fn installUrlOrBundleUrl(&self) -> Option<&str> { self.installUrlOrBundleUrl.as_deref() }
217}
218
219
220pub struct InstallParamsBuilder<'a> {
221    manifestId: Cow<'a, str>,
222    installUrlOrBundleUrl: Option<Cow<'a, str>>,
223}
224
225impl<'a> InstallParamsBuilder<'a> {
226    /// The location of the app or bundle overriding the one derived from the
227    /// manifestId.
228    pub fn installUrlOrBundleUrl(mut self, installUrlOrBundleUrl: impl Into<Cow<'a, str>>) -> Self { self.installUrlOrBundleUrl = Some(installUrlOrBundleUrl.into()); self }
229    pub fn build(self) -> InstallParams<'a> {
230        InstallParams {
231            manifestId: self.manifestId,
232            installUrlOrBundleUrl: self.installUrlOrBundleUrl,
233        }
234    }
235}
236
237impl<'a> InstallParams<'a> { pub const METHOD: &'static str = "PWA.install"; }
238
239impl<'a> crate::CdpCommand<'a> for InstallParams<'a> {
240    const METHOD: &'static str = "PWA.install";
241    type Response = crate::EmptyReturns;
242}
243
244/// Uninstalls the given manifest_id and closes any opened app windows.
245
246#[derive(Debug, Clone, Serialize, Deserialize, Default)]
247#[serde(rename_all = "camelCase")]
248pub struct UninstallParams<'a> {
249    manifestId: Cow<'a, str>,
250}
251
252impl<'a> UninstallParams<'a> {
253    pub fn builder(manifestId: impl Into<Cow<'a, str>>) -> UninstallParamsBuilder<'a> {
254        UninstallParamsBuilder {
255            manifestId: manifestId.into(),
256        }
257    }
258    pub fn manifestId(&self) -> &str { self.manifestId.as_ref() }
259}
260
261
262pub struct UninstallParamsBuilder<'a> {
263    manifestId: Cow<'a, str>,
264}
265
266impl<'a> UninstallParamsBuilder<'a> {
267    pub fn build(self) -> UninstallParams<'a> {
268        UninstallParams {
269            manifestId: self.manifestId,
270        }
271    }
272}
273
274impl<'a> UninstallParams<'a> { pub const METHOD: &'static str = "PWA.uninstall"; }
275
276impl<'a> crate::CdpCommand<'a> for UninstallParams<'a> {
277    const METHOD: &'static str = "PWA.uninstall";
278    type Response = crate::EmptyReturns;
279}
280
281/// Launches the installed web app, or an url in the same web app instead of the
282/// default start url if it is provided. Returns a page Target.TargetID which
283/// can be used to attach to via Target.attachToTarget or similar APIs.
284
285#[derive(Debug, Clone, Serialize, Deserialize, Default)]
286#[serde(rename_all = "camelCase")]
287pub struct LaunchParams<'a> {
288    manifestId: Cow<'a, str>,
289    #[serde(skip_serializing_if = "Option::is_none")]
290    url: Option<Cow<'a, str>>,
291}
292
293impl<'a> LaunchParams<'a> {
294    pub fn builder(manifestId: impl Into<Cow<'a, str>>) -> LaunchParamsBuilder<'a> {
295        LaunchParamsBuilder {
296            manifestId: manifestId.into(),
297            url: None,
298        }
299    }
300    pub fn manifestId(&self) -> &str { self.manifestId.as_ref() }
301    pub fn url(&self) -> Option<&str> { self.url.as_deref() }
302}
303
304
305pub struct LaunchParamsBuilder<'a> {
306    manifestId: Cow<'a, str>,
307    url: Option<Cow<'a, str>>,
308}
309
310impl<'a> LaunchParamsBuilder<'a> {
311    pub fn url(mut self, url: impl Into<Cow<'a, str>>) -> Self { self.url = Some(url.into()); self }
312    pub fn build(self) -> LaunchParams<'a> {
313        LaunchParams {
314            manifestId: self.manifestId,
315            url: self.url,
316        }
317    }
318}
319
320/// Launches the installed web app, or an url in the same web app instead of the
321/// default start url if it is provided. Returns a page Target.TargetID which
322/// can be used to attach to via Target.attachToTarget or similar APIs.
323
324#[derive(Debug, Clone, Serialize, Deserialize, Default)]
325#[serde(rename_all = "camelCase")]
326pub struct LaunchReturns<'a> {
327    /// ID of the tab target created as a result.
328    targetId: crate::target::TargetID<'a>,
329}
330
331impl<'a> LaunchReturns<'a> {
332    pub fn builder(targetId: crate::target::TargetID<'a>) -> LaunchReturnsBuilder<'a> {
333        LaunchReturnsBuilder {
334            targetId: targetId,
335        }
336    }
337    pub fn targetId(&self) -> &crate::target::TargetID<'a> { &self.targetId }
338}
339
340
341pub struct LaunchReturnsBuilder<'a> {
342    targetId: crate::target::TargetID<'a>,
343}
344
345impl<'a> LaunchReturnsBuilder<'a> {
346    pub fn build(self) -> LaunchReturns<'a> {
347        LaunchReturns {
348            targetId: self.targetId,
349        }
350    }
351}
352
353impl<'a> LaunchParams<'a> { pub const METHOD: &'static str = "PWA.launch"; }
354
355impl<'a> crate::CdpCommand<'a> for LaunchParams<'a> {
356    const METHOD: &'static str = "PWA.launch";
357    type Response = LaunchReturns<'a>;
358}
359
360/// Opens one or more local files from an installed web app identified by its
361/// manifestId. The web app needs to have file handlers registered to process
362/// the files. The API returns one or more page Target.TargetIDs which can be
363/// used to attach to via Target.attachToTarget or similar APIs.
364/// If some files in the parameters cannot be handled by the web app, they will
365/// be ignored. If none of the files can be handled, this API returns an error.
366/// If no files are provided as the parameter, this API also returns an error.
367/// 
368/// According to the definition of the file handlers in the manifest file, one
369/// Target.TargetID may represent a page handling one or more files. The order
370/// of the returned Target.TargetIDs is not guaranteed.
371/// 
372/// TODO(crbug.com/339454034): Check the existences of the input files.
373
374#[derive(Debug, Clone, Serialize, Deserialize, Default)]
375#[serde(rename_all = "camelCase")]
376pub struct LaunchFilesInAppParams<'a> {
377    manifestId: Cow<'a, str>,
378    files: Vec<Cow<'a, str>>,
379}
380
381impl<'a> LaunchFilesInAppParams<'a> {
382    pub fn builder(manifestId: impl Into<Cow<'a, str>>, files: Vec<Cow<'a, str>>) -> LaunchFilesInAppParamsBuilder<'a> {
383        LaunchFilesInAppParamsBuilder {
384            manifestId: manifestId.into(),
385            files: files,
386        }
387    }
388    pub fn manifestId(&self) -> &str { self.manifestId.as_ref() }
389    pub fn files(&self) -> &[Cow<'a, str>] { &self.files }
390}
391
392
393pub struct LaunchFilesInAppParamsBuilder<'a> {
394    manifestId: Cow<'a, str>,
395    files: Vec<Cow<'a, str>>,
396}
397
398impl<'a> LaunchFilesInAppParamsBuilder<'a> {
399    pub fn build(self) -> LaunchFilesInAppParams<'a> {
400        LaunchFilesInAppParams {
401            manifestId: self.manifestId,
402            files: self.files,
403        }
404    }
405}
406
407/// Opens one or more local files from an installed web app identified by its
408/// manifestId. The web app needs to have file handlers registered to process
409/// the files. The API returns one or more page Target.TargetIDs which can be
410/// used to attach to via Target.attachToTarget or similar APIs.
411/// If some files in the parameters cannot be handled by the web app, they will
412/// be ignored. If none of the files can be handled, this API returns an error.
413/// If no files are provided as the parameter, this API also returns an error.
414/// 
415/// According to the definition of the file handlers in the manifest file, one
416/// Target.TargetID may represent a page handling one or more files. The order
417/// of the returned Target.TargetIDs is not guaranteed.
418/// 
419/// TODO(crbug.com/339454034): Check the existences of the input files.
420
421#[derive(Debug, Clone, Serialize, Deserialize, Default)]
422#[serde(rename_all = "camelCase")]
423pub struct LaunchFilesInAppReturns<'a> {
424    /// IDs of the tab targets created as the result.
425    targetIds: Vec<crate::target::TargetID<'a>>,
426}
427
428impl<'a> LaunchFilesInAppReturns<'a> {
429    pub fn builder(targetIds: Vec<crate::target::TargetID<'a>>) -> LaunchFilesInAppReturnsBuilder<'a> {
430        LaunchFilesInAppReturnsBuilder {
431            targetIds: targetIds,
432        }
433    }
434    pub fn targetIds(&self) -> &[crate::target::TargetID<'a>] { &self.targetIds }
435}
436
437
438pub struct LaunchFilesInAppReturnsBuilder<'a> {
439    targetIds: Vec<crate::target::TargetID<'a>>,
440}
441
442impl<'a> LaunchFilesInAppReturnsBuilder<'a> {
443    pub fn build(self) -> LaunchFilesInAppReturns<'a> {
444        LaunchFilesInAppReturns {
445            targetIds: self.targetIds,
446        }
447    }
448}
449
450impl<'a> LaunchFilesInAppParams<'a> { pub const METHOD: &'static str = "PWA.launchFilesInApp"; }
451
452impl<'a> crate::CdpCommand<'a> for LaunchFilesInAppParams<'a> {
453    const METHOD: &'static str = "PWA.launchFilesInApp";
454    type Response = LaunchFilesInAppReturns<'a>;
455}
456
457/// Opens the current page in its web app identified by the manifest id, needs
458/// to be called on a page target. This function returns immediately without
459/// waiting for the app to finish loading.
460
461#[derive(Debug, Clone, Serialize, Deserialize, Default)]
462#[serde(rename_all = "camelCase")]
463pub struct OpenCurrentPageInAppParams<'a> {
464    manifestId: Cow<'a, str>,
465}
466
467impl<'a> OpenCurrentPageInAppParams<'a> {
468    pub fn builder(manifestId: impl Into<Cow<'a, str>>) -> OpenCurrentPageInAppParamsBuilder<'a> {
469        OpenCurrentPageInAppParamsBuilder {
470            manifestId: manifestId.into(),
471        }
472    }
473    pub fn manifestId(&self) -> &str { self.manifestId.as_ref() }
474}
475
476
477pub struct OpenCurrentPageInAppParamsBuilder<'a> {
478    manifestId: Cow<'a, str>,
479}
480
481impl<'a> OpenCurrentPageInAppParamsBuilder<'a> {
482    pub fn build(self) -> OpenCurrentPageInAppParams<'a> {
483        OpenCurrentPageInAppParams {
484            manifestId: self.manifestId,
485        }
486    }
487}
488
489impl<'a> OpenCurrentPageInAppParams<'a> { pub const METHOD: &'static str = "PWA.openCurrentPageInApp"; }
490
491impl<'a> crate::CdpCommand<'a> for OpenCurrentPageInAppParams<'a> {
492    const METHOD: &'static str = "PWA.openCurrentPageInApp";
493    type Response = crate::EmptyReturns;
494}
495
496/// Changes user settings of the web app identified by its manifestId. If the
497/// app was not installed, this command returns an error. Unset parameters will
498/// be ignored; unrecognized values will cause an error.
499/// 
500/// Unlike the ones defined in the manifest files of the web apps, these
501/// settings are provided by the browser and controlled by the users, they
502/// impact the way the browser handling the web apps.
503/// 
504/// See the comment of each parameter.
505
506#[derive(Debug, Clone, Serialize, Deserialize, Default)]
507#[serde(rename_all = "camelCase")]
508pub struct ChangeAppUserSettingsParams<'a> {
509    manifestId: Cow<'a, str>,
510    /// If user allows the links clicked on by the user in the app's scope, or
511    /// extended scope if the manifest has scope extensions and the flags
512    /// 'DesktopPWAsLinkCapturingWithScopeExtensions' and
513    /// 'WebAppEnableScopeExtensions' are enabled.
514    /// 
515    /// Note, the API does not support resetting the linkCapturing to the
516    /// initial value, uninstalling and installing the web app again will reset
517    /// it.
518    /// 
519    /// TODO(crbug.com/339453269): Setting this value on ChromeOS is not
520    /// supported yet.
521    #[serde(skip_serializing_if = "Option::is_none")]
522    linkCapturing: Option<bool>,
523    #[serde(skip_serializing_if = "Option::is_none")]
524    displayMode: Option<DisplayMode>,
525}
526
527impl<'a> ChangeAppUserSettingsParams<'a> {
528    pub fn builder(manifestId: impl Into<Cow<'a, str>>) -> ChangeAppUserSettingsParamsBuilder<'a> {
529        ChangeAppUserSettingsParamsBuilder {
530            manifestId: manifestId.into(),
531            linkCapturing: None,
532            displayMode: None,
533        }
534    }
535    pub fn manifestId(&self) -> &str { self.manifestId.as_ref() }
536    pub fn linkCapturing(&self) -> Option<bool> { self.linkCapturing }
537    pub fn displayMode(&self) -> Option<&DisplayMode> { self.displayMode.as_ref() }
538}
539
540
541pub struct ChangeAppUserSettingsParamsBuilder<'a> {
542    manifestId: Cow<'a, str>,
543    linkCapturing: Option<bool>,
544    displayMode: Option<DisplayMode>,
545}
546
547impl<'a> ChangeAppUserSettingsParamsBuilder<'a> {
548    /// If user allows the links clicked on by the user in the app's scope, or
549    /// extended scope if the manifest has scope extensions and the flags
550    /// 'DesktopPWAsLinkCapturingWithScopeExtensions' and
551    /// 'WebAppEnableScopeExtensions' are enabled.
552    /// 
553    /// Note, the API does not support resetting the linkCapturing to the
554    /// initial value, uninstalling and installing the web app again will reset
555    /// it.
556    /// 
557    /// TODO(crbug.com/339453269): Setting this value on ChromeOS is not
558    /// supported yet.
559    pub fn linkCapturing(mut self, linkCapturing: bool) -> Self { self.linkCapturing = Some(linkCapturing); self }
560    pub fn displayMode(mut self, displayMode: DisplayMode) -> Self { self.displayMode = Some(displayMode); self }
561    pub fn build(self) -> ChangeAppUserSettingsParams<'a> {
562        ChangeAppUserSettingsParams {
563            manifestId: self.manifestId,
564            linkCapturing: self.linkCapturing,
565            displayMode: self.displayMode,
566        }
567    }
568}
569
570impl<'a> ChangeAppUserSettingsParams<'a> { pub const METHOD: &'static str = "PWA.changeAppUserSettings"; }
571
572impl<'a> crate::CdpCommand<'a> for ChangeAppUserSettingsParams<'a> {
573    const METHOD: &'static str = "PWA.changeAppUserSettings";
574    type Response = crate::EmptyReturns;
575}