places/
observation.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use crate::types::*;
6use types::Timestamp;
7use url::Url;
8
9/// An "observation" based model for updating history.
10/// You create a VisitObservation, call functions on it which correspond
11/// with what you observed. The page will then be updated using this info.
12///
13/// It's implemented such that the making of an "observation" is itself
14/// significant - it records what specific changes should be made to storage.
15/// For example, instead of simple bools with defaults (where you can't
16/// differentiate explicitly setting a value from the default value), we use
17/// Option<bool>, with the idea being it's better for a store shaped like Mentat.
18///
19/// It exposes a "builder api", but for convenience, that API allows Options too.
20/// So, eg, `.with_title(None)` or `with_is_error(None)` is allowed but records
21/// no observation.
22#[derive(Clone, Debug)]
23pub struct VisitObservation {
24    pub url: Url,
25    pub title: Option<String>,
26    pub visit_type: Option<VisitType>,
27    pub is_error: Option<bool>,
28    pub is_redirect_source: Option<bool>,
29    pub is_permanent_redirect_source: Option<bool>,
30    pub at: Option<Timestamp>,
31    pub referrer: Option<Url>,
32    pub is_remote: Option<bool>,
33    pub preview_image_url: Option<Url>,
34}
35
36impl VisitObservation {
37    pub fn new(url: Url) -> Self {
38        VisitObservation {
39            url,
40            title: None,
41            visit_type: None,
42            is_error: None,
43            is_redirect_source: None,
44            is_permanent_redirect_source: None,
45            at: None,
46            referrer: None,
47            is_remote: None,
48            preview_image_url: None,
49        }
50    }
51
52    // A "builder" API to sanely build an observation. Note that this can be
53    // called with Option<String> (and if None will effectively be a no-op)
54    // or directly with a string.
55    pub fn with_title(mut self, t: impl Into<Option<String>>) -> Self {
56        self.title = t.into();
57        self
58    }
59
60    pub fn with_visit_type(mut self, t: impl Into<Option<VisitType>>) -> Self {
61        self.visit_type = t.into();
62        self
63    }
64
65    pub fn with_is_error(mut self, v: impl Into<Option<bool>>) -> Self {
66        self.is_error = v.into();
67        self
68    }
69
70    pub fn with_is_redirect_source(mut self, v: impl Into<Option<bool>>) -> Self {
71        self.is_redirect_source = v.into();
72        self
73    }
74
75    pub fn with_is_permanent_redirect_source(mut self, v: impl Into<Option<bool>>) -> Self {
76        self.is_permanent_redirect_source = v.into();
77        self
78    }
79
80    pub fn with_at(mut self, v: impl Into<Option<Timestamp>>) -> Self {
81        self.at = v.into();
82        self
83    }
84
85    pub fn with_is_remote(mut self, v: impl Into<Option<bool>>) -> Self {
86        self.is_remote = v.into();
87        self
88    }
89
90    pub fn with_referrer(mut self, v: impl Into<Option<Url>>) -> Self {
91        self.referrer = v.into();
92        self
93    }
94
95    pub fn with_preview_image_url(mut self, v: impl Into<Option<Url>>) -> Self {
96        self.preview_image_url = v.into();
97        self
98    }
99
100    // Other helpers which can be derived.
101    pub fn get_redirect_frecency_boost(&self) -> bool {
102        self.is_redirect_source.is_some()
103            && match self.visit_type {
104                Some(t) => t != VisitType::Typed,
105                _ => true,
106            }
107    }
108
109    // nsHistory::GetHiddenState()
110    pub fn get_is_hidden(&self) -> bool {
111        match self.visit_type {
112            Some(visit_type) => {
113                self.is_redirect_source.is_some()
114                    || visit_type == VisitType::FramedLink
115                    || visit_type == VisitType::Embed
116            }
117            None => false,
118        }
119    }
120}