Skip to main content

browser_protocol/preload/
mod.rs

1use serde::{Serialize, Deserialize};
2use serde_json::Value as JsonValue;
3use std::borrow::Cow;
4
5/// Unique id
6
7pub type RuleSetId<'a> = Cow<'a, str>;
8
9/// Corresponds to SpeculationRuleSet
10
11#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12#[serde(rename_all = "camelCase")]
13pub struct RuleSet<'a> {
14    id: RuleSetId<'a>,
15    /// Identifies a document which the rule set is associated with.
16    loaderId: crate::network::LoaderId<'a>,
17    /// Source text of JSON representing the rule set. If it comes from
18    /// '<script>' tag, it is the textContent of the node. Note that it is
19    /// a JSON for valid case.
20    /// 
21    /// See also:
22    /// - https://wicg.github.io/nav-speculation/speculation-rules.html
23    /// - https://github.com/WICG/nav-speculation/blob/main/triggers.md
24    sourceText: Cow<'a, str>,
25    /// A speculation rule set is either added through an inline
26    /// '<script>' tag or through an external resource via the
27    /// 'Speculation-Rules' HTTP header. For the first case, we include
28    /// the BackendNodeId of the relevant '<script>' tag. For the second
29    /// case, we include the external URL where the rule set was loaded
30    /// from, and also RequestId if Network domain is enabled.
31    /// 
32    /// See also:
33    /// - https://wicg.github.io/nav-speculation/speculation-rules.html#speculation-rules-script
34    /// - https://wicg.github.io/nav-speculation/speculation-rules.html#speculation-rules-header
35    #[serde(skip_serializing_if = "Option::is_none")]
36    backendNodeId: Option<crate::dom::BackendNodeId>,
37    #[serde(skip_serializing_if = "Option::is_none")]
38    url: Option<Cow<'a, str>>,
39    #[serde(skip_serializing_if = "Option::is_none")]
40    requestId: Option<crate::network::RequestId<'a>>,
41    /// Error information
42    /// 'errorMessage' is null iff 'errorType' is null.
43    #[serde(skip_serializing_if = "Option::is_none")]
44    errorType: Option<RuleSetErrorType>,
45    /// TODO(https://crbug.com/1425354): Replace this property with structured error.
46    #[serde(skip_serializing_if = "Option::is_none")]
47    errorMessage: Option<Cow<'a, str>>,
48    /// For more details, see:
49    /// https://github.com/WICG/nav-speculation/blob/main/speculation-rules-tags.md
50    #[serde(skip_serializing_if = "Option::is_none")]
51    tag: Option<Cow<'a, str>>,
52}
53
54impl<'a> RuleSet<'a> {
55    pub fn builder(id: RuleSetId<'a>, loaderId: crate::network::LoaderId<'a>, sourceText: impl Into<Cow<'a, str>>) -> RuleSetBuilder<'a> {
56        RuleSetBuilder {
57            id: id,
58            loaderId: loaderId,
59            sourceText: sourceText.into(),
60            backendNodeId: None,
61            url: None,
62            requestId: None,
63            errorType: None,
64            errorMessage: None,
65            tag: None,
66        }
67    }
68    pub fn id(&self) -> &RuleSetId<'a> { &self.id }
69    pub fn loaderId(&self) -> &crate::network::LoaderId<'a> { &self.loaderId }
70    pub fn sourceText(&self) -> &str { self.sourceText.as_ref() }
71    pub fn backendNodeId(&self) -> Option<&crate::dom::BackendNodeId> { self.backendNodeId.as_ref() }
72    pub fn url(&self) -> Option<&str> { self.url.as_deref() }
73    pub fn requestId(&self) -> Option<&crate::network::RequestId<'a>> { self.requestId.as_ref() }
74    pub fn errorType(&self) -> Option<&RuleSetErrorType> { self.errorType.as_ref() }
75    pub fn errorMessage(&self) -> Option<&str> { self.errorMessage.as_deref() }
76    pub fn tag(&self) -> Option<&str> { self.tag.as_deref() }
77}
78
79
80pub struct RuleSetBuilder<'a> {
81    id: RuleSetId<'a>,
82    loaderId: crate::network::LoaderId<'a>,
83    sourceText: Cow<'a, str>,
84    backendNodeId: Option<crate::dom::BackendNodeId>,
85    url: Option<Cow<'a, str>>,
86    requestId: Option<crate::network::RequestId<'a>>,
87    errorType: Option<RuleSetErrorType>,
88    errorMessage: Option<Cow<'a, str>>,
89    tag: Option<Cow<'a, str>>,
90}
91
92impl<'a> RuleSetBuilder<'a> {
93    /// A speculation rule set is either added through an inline
94    /// '<script>' tag or through an external resource via the
95    /// 'Speculation-Rules' HTTP header. For the first case, we include
96    /// the BackendNodeId of the relevant '<script>' tag. For the second
97    /// case, we include the external URL where the rule set was loaded
98    /// from, and also RequestId if Network domain is enabled.
99    /// 
100    /// See also:
101    /// - https://wicg.github.io/nav-speculation/speculation-rules.html#speculation-rules-script
102    /// - https://wicg.github.io/nav-speculation/speculation-rules.html#speculation-rules-header
103    pub fn backendNodeId(mut self, backendNodeId: crate::dom::BackendNodeId) -> Self { self.backendNodeId = Some(backendNodeId); self }
104    pub fn url(mut self, url: impl Into<Cow<'a, str>>) -> Self { self.url = Some(url.into()); self }
105    pub fn requestId(mut self, requestId: crate::network::RequestId<'a>) -> Self { self.requestId = Some(requestId); self }
106    /// Error information
107    /// 'errorMessage' is null iff 'errorType' is null.
108    pub fn errorType(mut self, errorType: RuleSetErrorType) -> Self { self.errorType = Some(errorType); self }
109    /// TODO(https://crbug.com/1425354): Replace this property with structured error.
110    pub fn errorMessage(mut self, errorMessage: impl Into<Cow<'a, str>>) -> Self { self.errorMessage = Some(errorMessage.into()); self }
111    /// For more details, see:
112    /// https://github.com/WICG/nav-speculation/blob/main/speculation-rules-tags.md
113    pub fn tag(mut self, tag: impl Into<Cow<'a, str>>) -> Self { self.tag = Some(tag.into()); self }
114    pub fn build(self) -> RuleSet<'a> {
115        RuleSet {
116            id: self.id,
117            loaderId: self.loaderId,
118            sourceText: self.sourceText,
119            backendNodeId: self.backendNodeId,
120            url: self.url,
121            requestId: self.requestId,
122            errorType: self.errorType,
123            errorMessage: self.errorMessage,
124            tag: self.tag,
125        }
126    }
127}
128
129
130#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
131pub enum RuleSetErrorType {
132    #[default]
133    #[serde(rename = "SourceIsNotJsonObject")]
134    SourceIsNotJsonObject,
135    #[serde(rename = "InvalidRulesSkipped")]
136    InvalidRulesSkipped,
137    #[serde(rename = "InvalidRulesetLevelTag")]
138    InvalidRulesetLevelTag,
139}
140
141/// The type of preloading attempted. It corresponds to
142/// mojom::SpeculationAction (although PrefetchWithSubresources is omitted as it
143/// isn't being used by clients).
144
145#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
146pub enum SpeculationAction {
147    #[default]
148    #[serde(rename = "Prefetch")]
149    Prefetch,
150    #[serde(rename = "Prerender")]
151    Prerender,
152    #[serde(rename = "PrerenderUntilScript")]
153    PrerenderUntilScript,
154}
155
156/// Corresponds to mojom::SpeculationTargetHint.
157/// See https://github.com/WICG/nav-speculation/blob/main/triggers.md#window-name-targeting-hints
158
159#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
160pub enum SpeculationTargetHint {
161    #[default]
162    #[serde(rename = "Blank")]
163    Blank,
164    #[serde(rename = "Self")]
165    SelfValue,
166}
167
168/// A key that identifies a preloading attempt.
169/// 
170/// The url used is the url specified by the trigger (i.e. the initial URL), and
171/// not the final url that is navigated to. For example, prerendering allows
172/// same-origin main frame navigations during the attempt, but the attempt is
173/// still keyed with the initial URL.
174
175#[derive(Debug, Clone, Serialize, Deserialize, Default)]
176#[serde(rename_all = "camelCase")]
177pub struct PreloadingAttemptKey<'a> {
178    loaderId: crate::network::LoaderId<'a>,
179    action: SpeculationAction,
180    url: Cow<'a, str>,
181    #[serde(skip_serializing_if = "Option::is_none")]
182    formSubmission: Option<bool>,
183    #[serde(skip_serializing_if = "Option::is_none")]
184    targetHint: Option<SpeculationTargetHint>,
185}
186
187impl<'a> PreloadingAttemptKey<'a> {
188    pub fn builder(loaderId: crate::network::LoaderId<'a>, action: SpeculationAction, url: impl Into<Cow<'a, str>>) -> PreloadingAttemptKeyBuilder<'a> {
189        PreloadingAttemptKeyBuilder {
190            loaderId: loaderId,
191            action: action,
192            url: url.into(),
193            formSubmission: None,
194            targetHint: None,
195        }
196    }
197    pub fn loaderId(&self) -> &crate::network::LoaderId<'a> { &self.loaderId }
198    pub fn action(&self) -> &SpeculationAction { &self.action }
199    pub fn url(&self) -> &str { self.url.as_ref() }
200    pub fn formSubmission(&self) -> Option<bool> { self.formSubmission }
201    pub fn targetHint(&self) -> Option<&SpeculationTargetHint> { self.targetHint.as_ref() }
202}
203
204
205pub struct PreloadingAttemptKeyBuilder<'a> {
206    loaderId: crate::network::LoaderId<'a>,
207    action: SpeculationAction,
208    url: Cow<'a, str>,
209    formSubmission: Option<bool>,
210    targetHint: Option<SpeculationTargetHint>,
211}
212
213impl<'a> PreloadingAttemptKeyBuilder<'a> {
214    pub fn formSubmission(mut self, formSubmission: bool) -> Self { self.formSubmission = Some(formSubmission); self }
215    pub fn targetHint(mut self, targetHint: SpeculationTargetHint) -> Self { self.targetHint = Some(targetHint); self }
216    pub fn build(self) -> PreloadingAttemptKey<'a> {
217        PreloadingAttemptKey {
218            loaderId: self.loaderId,
219            action: self.action,
220            url: self.url,
221            formSubmission: self.formSubmission,
222            targetHint: self.targetHint,
223        }
224    }
225}
226
227/// Lists sources for a preloading attempt, specifically the ids of rule sets
228/// that had a speculation rule that triggered the attempt, and the
229/// BackendNodeIds of <a href> or <area href> elements that triggered the
230/// attempt (in the case of attempts triggered by a document rule). It is
231/// possible for multiple rule sets and links to trigger a single attempt.
232
233#[derive(Debug, Clone, Serialize, Deserialize, Default)]
234#[serde(rename_all = "camelCase")]
235pub struct PreloadingAttemptSource<'a> {
236    key: PreloadingAttemptKey<'a>,
237    ruleSetIds: Vec<RuleSetId<'a>>,
238    nodeIds: Vec<crate::dom::BackendNodeId>,
239}
240
241impl<'a> PreloadingAttemptSource<'a> {
242    pub fn builder(key: PreloadingAttemptKey<'a>, ruleSetIds: Vec<RuleSetId<'a>>, nodeIds: Vec<crate::dom::BackendNodeId>) -> PreloadingAttemptSourceBuilder<'a> {
243        PreloadingAttemptSourceBuilder {
244            key: key,
245            ruleSetIds: ruleSetIds,
246            nodeIds: nodeIds,
247        }
248    }
249    pub fn key(&self) -> &PreloadingAttemptKey<'a> { &self.key }
250    pub fn ruleSetIds(&self) -> &[RuleSetId<'a>] { &self.ruleSetIds }
251    pub fn nodeIds(&self) -> &[crate::dom::BackendNodeId] { &self.nodeIds }
252}
253
254
255pub struct PreloadingAttemptSourceBuilder<'a> {
256    key: PreloadingAttemptKey<'a>,
257    ruleSetIds: Vec<RuleSetId<'a>>,
258    nodeIds: Vec<crate::dom::BackendNodeId>,
259}
260
261impl<'a> PreloadingAttemptSourceBuilder<'a> {
262    pub fn build(self) -> PreloadingAttemptSource<'a> {
263        PreloadingAttemptSource {
264            key: self.key,
265            ruleSetIds: self.ruleSetIds,
266            nodeIds: self.nodeIds,
267        }
268    }
269}
270
271/// Chrome manages different types of preloads together using a
272/// concept of preloading pipeline. For example, if a site uses a
273/// SpeculationRules for prerender, Chrome first starts a prefetch and
274/// then upgrades it to prerender.
275/// 
276/// CDP events for them are emitted separately but they share
277/// 'PreloadPipelineId'.
278
279pub type PreloadPipelineId<'a> = Cow<'a, str>;
280
281/// List of FinalStatus reasons for Prerender2.
282
283#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
284pub enum PrerenderFinalStatus {
285    #[default]
286    #[serde(rename = "Activated")]
287    Activated,
288    #[serde(rename = "Destroyed")]
289    Destroyed,
290    #[serde(rename = "LowEndDevice")]
291    LowEndDevice,
292    #[serde(rename = "InvalidSchemeRedirect")]
293    InvalidSchemeRedirect,
294    #[serde(rename = "InvalidSchemeNavigation")]
295    InvalidSchemeNavigation,
296    #[serde(rename = "NavigationRequestBlockedByCsp")]
297    NavigationRequestBlockedByCsp,
298    #[serde(rename = "MojoBinderPolicy")]
299    MojoBinderPolicy,
300    #[serde(rename = "RendererProcessCrashed")]
301    RendererProcessCrashed,
302    #[serde(rename = "RendererProcessKilled")]
303    RendererProcessKilled,
304    #[serde(rename = "Download")]
305    Download,
306    #[serde(rename = "TriggerDestroyed")]
307    TriggerDestroyed,
308    #[serde(rename = "NavigationNotCommitted")]
309    NavigationNotCommitted,
310    #[serde(rename = "NavigationBadHttpStatus")]
311    NavigationBadHttpStatus,
312    #[serde(rename = "ClientCertRequested")]
313    ClientCertRequested,
314    #[serde(rename = "NavigationRequestNetworkError")]
315    NavigationRequestNetworkError,
316    #[serde(rename = "CancelAllHostsForTesting")]
317    CancelAllHostsForTesting,
318    #[serde(rename = "DidFailLoad")]
319    DidFailLoad,
320    #[serde(rename = "Stop")]
321    Stop,
322    #[serde(rename = "SslCertificateError")]
323    SslCertificateError,
324    #[serde(rename = "LoginAuthRequested")]
325    LoginAuthRequested,
326    #[serde(rename = "UaChangeRequiresReload")]
327    UaChangeRequiresReload,
328    #[serde(rename = "BlockedByClient")]
329    BlockedByClient,
330    #[serde(rename = "AudioOutputDeviceRequested")]
331    AudioOutputDeviceRequested,
332    #[serde(rename = "MixedContent")]
333    MixedContent,
334    #[serde(rename = "TriggerBackgrounded")]
335    TriggerBackgrounded,
336    #[serde(rename = "MemoryLimitExceeded")]
337    MemoryLimitExceeded,
338    #[serde(rename = "DataSaverEnabled")]
339    DataSaverEnabled,
340    #[serde(rename = "TriggerUrlHasEffectiveUrl")]
341    TriggerUrlHasEffectiveUrl,
342    #[serde(rename = "ActivatedBeforeStarted")]
343    ActivatedBeforeStarted,
344    #[serde(rename = "InactivePageRestriction")]
345    InactivePageRestriction,
346    #[serde(rename = "StartFailed")]
347    StartFailed,
348    #[serde(rename = "TimeoutBackgrounded")]
349    TimeoutBackgrounded,
350    #[serde(rename = "CrossSiteRedirectInInitialNavigation")]
351    CrossSiteRedirectInInitialNavigation,
352    #[serde(rename = "CrossSiteNavigationInInitialNavigation")]
353    CrossSiteNavigationInInitialNavigation,
354    #[serde(rename = "SameSiteCrossOriginRedirectNotOptInInInitialNavigation")]
355    SameSiteCrossOriginRedirectNotOptInInInitialNavigation,
356    #[serde(rename = "SameSiteCrossOriginNavigationNotOptInInInitialNavigation")]
357    SameSiteCrossOriginNavigationNotOptInInInitialNavigation,
358    #[serde(rename = "ActivationNavigationParameterMismatch")]
359    ActivationNavigationParameterMismatch,
360    #[serde(rename = "ActivatedInBackground")]
361    ActivatedInBackground,
362    #[serde(rename = "EmbedderHostDisallowed")]
363    EmbedderHostDisallowed,
364    #[serde(rename = "ActivationNavigationDestroyedBeforeSuccess")]
365    ActivationNavigationDestroyedBeforeSuccess,
366    #[serde(rename = "TabClosedByUserGesture")]
367    TabClosedByUserGesture,
368    #[serde(rename = "TabClosedWithoutUserGesture")]
369    TabClosedWithoutUserGesture,
370    #[serde(rename = "PrimaryMainFrameRendererProcessCrashed")]
371    PrimaryMainFrameRendererProcessCrashed,
372    #[serde(rename = "PrimaryMainFrameRendererProcessKilled")]
373    PrimaryMainFrameRendererProcessKilled,
374    #[serde(rename = "ActivationFramePolicyNotCompatible")]
375    ActivationFramePolicyNotCompatible,
376    #[serde(rename = "PreloadingDisabled")]
377    PreloadingDisabled,
378    #[serde(rename = "BatterySaverEnabled")]
379    BatterySaverEnabled,
380    #[serde(rename = "ActivatedDuringMainFrameNavigation")]
381    ActivatedDuringMainFrameNavigation,
382    #[serde(rename = "PreloadingUnsupportedByWebContents")]
383    PreloadingUnsupportedByWebContents,
384    #[serde(rename = "CrossSiteRedirectInMainFrameNavigation")]
385    CrossSiteRedirectInMainFrameNavigation,
386    #[serde(rename = "CrossSiteNavigationInMainFrameNavigation")]
387    CrossSiteNavigationInMainFrameNavigation,
388    #[serde(rename = "SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation")]
389    SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation,
390    #[serde(rename = "SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation")]
391    SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation,
392    #[serde(rename = "MemoryPressureOnTrigger")]
393    MemoryPressureOnTrigger,
394    #[serde(rename = "MemoryPressureAfterTriggered")]
395    MemoryPressureAfterTriggered,
396    #[serde(rename = "PrerenderingDisabledByDevTools")]
397    PrerenderingDisabledByDevTools,
398    #[serde(rename = "SpeculationRuleRemoved")]
399    SpeculationRuleRemoved,
400    #[serde(rename = "ActivatedWithAuxiliaryBrowsingContexts")]
401    ActivatedWithAuxiliaryBrowsingContexts,
402    #[serde(rename = "MaxNumOfRunningEagerPrerendersExceeded")]
403    MaxNumOfRunningEagerPrerendersExceeded,
404    #[serde(rename = "MaxNumOfRunningNonEagerPrerendersExceeded")]
405    MaxNumOfRunningNonEagerPrerendersExceeded,
406    #[serde(rename = "MaxNumOfRunningEmbedderPrerendersExceeded")]
407    MaxNumOfRunningEmbedderPrerendersExceeded,
408    #[serde(rename = "PrerenderingUrlHasEffectiveUrl")]
409    PrerenderingUrlHasEffectiveUrl,
410    #[serde(rename = "RedirectedPrerenderingUrlHasEffectiveUrl")]
411    RedirectedPrerenderingUrlHasEffectiveUrl,
412    #[serde(rename = "ActivationUrlHasEffectiveUrl")]
413    ActivationUrlHasEffectiveUrl,
414    #[serde(rename = "JavaScriptInterfaceAdded")]
415    JavaScriptInterfaceAdded,
416    #[serde(rename = "JavaScriptInterfaceRemoved")]
417    JavaScriptInterfaceRemoved,
418    #[serde(rename = "AllPrerenderingCanceled")]
419    AllPrerenderingCanceled,
420    #[serde(rename = "WindowClosed")]
421    WindowClosed,
422    #[serde(rename = "SlowNetwork")]
423    SlowNetwork,
424    #[serde(rename = "OtherPrerenderedPageActivated")]
425    OtherPrerenderedPageActivated,
426    #[serde(rename = "V8OptimizerDisabled")]
427    V8OptimizerDisabled,
428    #[serde(rename = "PrerenderFailedDuringPrefetch")]
429    PrerenderFailedDuringPrefetch,
430    #[serde(rename = "BrowsingDataRemoved")]
431    BrowsingDataRemoved,
432    #[serde(rename = "PrerenderHostReused")]
433    PrerenderHostReused,
434    #[serde(rename = "FormSubmitWhenPrerendering")]
435    FormSubmitWhenPrerendering,
436}
437
438/// Preloading status values, see also PreloadingTriggeringOutcome. This
439/// status is shared by prefetchStatusUpdated and prerenderStatusUpdated.
440
441#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
442pub enum PreloadingStatus {
443    #[default]
444    #[serde(rename = "Pending")]
445    Pending,
446    #[serde(rename = "Running")]
447    Running,
448    #[serde(rename = "Ready")]
449    Ready,
450    #[serde(rename = "Success")]
451    Success,
452    #[serde(rename = "Failure")]
453    Failure,
454    #[serde(rename = "NotSupported")]
455    NotSupported,
456}
457
458/// TODO(https://crbug.com/1384419): revisit the list of PrefetchStatus and
459/// filter out the ones that aren't necessary to the developers.
460
461#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
462pub enum PrefetchStatus {
463    #[default]
464    #[serde(rename = "PrefetchAllowed")]
465    PrefetchAllowed,
466    #[serde(rename = "PrefetchFailedIneligibleRedirect")]
467    PrefetchFailedIneligibleRedirect,
468    #[serde(rename = "PrefetchFailedInvalidRedirect")]
469    PrefetchFailedInvalidRedirect,
470    #[serde(rename = "PrefetchFailedMIMENotSupported")]
471    PrefetchFailedMIMENotSupported,
472    #[serde(rename = "PrefetchFailedNetError")]
473    PrefetchFailedNetError,
474    #[serde(rename = "PrefetchFailedNon2XX")]
475    PrefetchFailedNon2XX,
476    #[serde(rename = "PrefetchEvictedAfterBrowsingDataRemoved")]
477    PrefetchEvictedAfterBrowsingDataRemoved,
478    #[serde(rename = "PrefetchEvictedAfterCandidateRemoved")]
479    PrefetchEvictedAfterCandidateRemoved,
480    #[serde(rename = "PrefetchEvictedForNewerPrefetch")]
481    PrefetchEvictedForNewerPrefetch,
482    #[serde(rename = "PrefetchHeldback")]
483    PrefetchHeldback,
484    #[serde(rename = "PrefetchIneligibleRetryAfter")]
485    PrefetchIneligibleRetryAfter,
486    #[serde(rename = "PrefetchIsPrivacyDecoy")]
487    PrefetchIsPrivacyDecoy,
488    #[serde(rename = "PrefetchIsStale")]
489    PrefetchIsStale,
490    #[serde(rename = "PrefetchNotEligibleBrowserContextOffTheRecord")]
491    PrefetchNotEligibleBrowserContextOffTheRecord,
492    #[serde(rename = "PrefetchNotEligibleDataSaverEnabled")]
493    PrefetchNotEligibleDataSaverEnabled,
494    #[serde(rename = "PrefetchNotEligibleExistingProxy")]
495    PrefetchNotEligibleExistingProxy,
496    #[serde(rename = "PrefetchNotEligibleHostIsNonUnique")]
497    PrefetchNotEligibleHostIsNonUnique,
498    #[serde(rename = "PrefetchNotEligibleNonDefaultStoragePartition")]
499    PrefetchNotEligibleNonDefaultStoragePartition,
500    #[serde(rename = "PrefetchNotEligibleSameSiteCrossOriginPrefetchRequiredProxy")]
501    PrefetchNotEligibleSameSiteCrossOriginPrefetchRequiredProxy,
502    #[serde(rename = "PrefetchNotEligibleSchemeIsNotHttps")]
503    PrefetchNotEligibleSchemeIsNotHttps,
504    #[serde(rename = "PrefetchNotEligibleUserHasCookies")]
505    PrefetchNotEligibleUserHasCookies,
506    #[serde(rename = "PrefetchNotEligibleUserHasServiceWorker")]
507    PrefetchNotEligibleUserHasServiceWorker,
508    #[serde(rename = "PrefetchNotEligibleUserHasServiceWorkerNoFetchHandler")]
509    PrefetchNotEligibleUserHasServiceWorkerNoFetchHandler,
510    #[serde(rename = "PrefetchNotEligibleRedirectFromServiceWorker")]
511    PrefetchNotEligibleRedirectFromServiceWorker,
512    #[serde(rename = "PrefetchNotEligibleRedirectToServiceWorker")]
513    PrefetchNotEligibleRedirectToServiceWorker,
514    #[serde(rename = "PrefetchNotEligibleBatterySaverEnabled")]
515    PrefetchNotEligibleBatterySaverEnabled,
516    #[serde(rename = "PrefetchNotEligiblePreloadingDisabled")]
517    PrefetchNotEligiblePreloadingDisabled,
518    #[serde(rename = "PrefetchNotFinishedInTime")]
519    PrefetchNotFinishedInTime,
520    #[serde(rename = "PrefetchNotStarted")]
521    PrefetchNotStarted,
522    #[serde(rename = "PrefetchNotUsedCookiesChanged")]
523    PrefetchNotUsedCookiesChanged,
524    #[serde(rename = "PrefetchProxyNotAvailable")]
525    PrefetchProxyNotAvailable,
526    #[serde(rename = "PrefetchResponseUsed")]
527    PrefetchResponseUsed,
528    #[serde(rename = "PrefetchSuccessfulButNotUsed")]
529    PrefetchSuccessfulButNotUsed,
530    #[serde(rename = "PrefetchNotUsedProbeFailed")]
531    PrefetchNotUsedProbeFailed,
532}
533
534/// Information of headers to be displayed when the header mismatch occurred.
535
536#[derive(Debug, Clone, Serialize, Deserialize, Default)]
537#[serde(rename_all = "camelCase")]
538pub struct PrerenderMismatchedHeaders<'a> {
539    headerName: Cow<'a, str>,
540    #[serde(skip_serializing_if = "Option::is_none")]
541    initialValue: Option<Cow<'a, str>>,
542    #[serde(skip_serializing_if = "Option::is_none")]
543    activationValue: Option<Cow<'a, str>>,
544}
545
546impl<'a> PrerenderMismatchedHeaders<'a> {
547    pub fn builder(headerName: impl Into<Cow<'a, str>>) -> PrerenderMismatchedHeadersBuilder<'a> {
548        PrerenderMismatchedHeadersBuilder {
549            headerName: headerName.into(),
550            initialValue: None,
551            activationValue: None,
552        }
553    }
554    pub fn headerName(&self) -> &str { self.headerName.as_ref() }
555    pub fn initialValue(&self) -> Option<&str> { self.initialValue.as_deref() }
556    pub fn activationValue(&self) -> Option<&str> { self.activationValue.as_deref() }
557}
558
559
560pub struct PrerenderMismatchedHeadersBuilder<'a> {
561    headerName: Cow<'a, str>,
562    initialValue: Option<Cow<'a, str>>,
563    activationValue: Option<Cow<'a, str>>,
564}
565
566impl<'a> PrerenderMismatchedHeadersBuilder<'a> {
567    pub fn initialValue(mut self, initialValue: impl Into<Cow<'a, str>>) -> Self { self.initialValue = Some(initialValue.into()); self }
568    pub fn activationValue(mut self, activationValue: impl Into<Cow<'a, str>>) -> Self { self.activationValue = Some(activationValue.into()); self }
569    pub fn build(self) -> PrerenderMismatchedHeaders<'a> {
570        PrerenderMismatchedHeaders {
571            headerName: self.headerName,
572            initialValue: self.initialValue,
573            activationValue: self.activationValue,
574        }
575    }
576}
577
578#[derive(Debug, Clone, Serialize, Deserialize, Default)]
579pub struct EnableParams {}
580
581impl EnableParams { pub const METHOD: &'static str = "Preload.enable"; }
582
583impl<'a> crate::CdpCommand<'a> for EnableParams {
584    const METHOD: &'static str = "Preload.enable";
585    type Response = crate::EmptyReturns;
586}
587
588#[derive(Debug, Clone, Serialize, Deserialize, Default)]
589pub struct DisableParams {}
590
591impl DisableParams { pub const METHOD: &'static str = "Preload.disable"; }
592
593impl<'a> crate::CdpCommand<'a> for DisableParams {
594    const METHOD: &'static str = "Preload.disable";
595    type Response = crate::EmptyReturns;
596}