tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

result.rs (5908B)


      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 
      5 use serde::de;
      6 use serde::{Deserialize, Deserializer, Serialize, Serializer};
      7 use serde_json::Value;
      8 
      9 use crate::common::{Cookie, Timeouts, WebElement};
     10 
     11 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
     12 pub struct NewWindow {
     13    handle: String,
     14    #[serde(rename = "type")]
     15    type_hint: String,
     16 }
     17 
     18 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
     19 pub struct WindowRect {
     20    pub x: i32,
     21    pub y: i32,
     22    pub width: i32,
     23    pub height: i32,
     24 }
     25 
     26 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
     27 pub struct ElementRect {
     28    pub x: f64,
     29    pub y: f64,
     30    pub width: f64,
     31    pub height: f64,
     32 }
     33 
     34 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
     35 #[serde(untagged)]
     36 pub enum MarionetteResult {
     37    #[serde(deserialize_with = "from_value", serialize_with = "to_value")]
     38    Bool(bool),
     39    #[serde(deserialize_with = "from_value", serialize_with = "to_empty_value")]
     40    Null,
     41    NewWindow(NewWindow),
     42    WindowRect(WindowRect),
     43    ElementRect(ElementRect),
     44    #[serde(deserialize_with = "from_value", serialize_with = "to_value")]
     45    String(String),
     46    Strings(Vec<String>),
     47    #[serde(deserialize_with = "from_value", serialize_with = "to_value")]
     48    WebElement(WebElement),
     49    WebElements(Vec<WebElement>),
     50    Cookies(Vec<Cookie>),
     51    Timeouts(Timeouts),
     52 }
     53 
     54 fn to_value<T, S>(data: T, serializer: S) -> Result<S::Ok, S::Error>
     55 where
     56    S: Serializer,
     57    T: Serialize,
     58 {
     59    #[derive(Serialize)]
     60    struct Wrapper<T> {
     61        value: T,
     62    }
     63 
     64    Wrapper { value: data }.serialize(serializer)
     65 }
     66 
     67 fn to_empty_value<S>(serializer: S) -> Result<S::Ok, S::Error>
     68 where
     69    S: Serializer,
     70 {
     71    #[derive(Serialize)]
     72    struct Wrapper {
     73        value: Value,
     74    }
     75 
     76    Wrapper { value: Value::Null }.serialize(serializer)
     77 }
     78 
     79 fn from_value<'de, D, T>(deserializer: D) -> Result<T, D::Error>
     80 where
     81    D: Deserializer<'de>,
     82    T: serde::de::DeserializeOwned,
     83    T: std::fmt::Debug,
     84 {
     85    #[derive(Debug, Deserialize)]
     86    struct Wrapper<T> {
     87        value: T,
     88    }
     89 
     90    let v = Value::deserialize(deserializer)?;
     91    if v.is_object() {
     92        let w = serde_json::from_value::<Wrapper<T>>(v).map_err(de::Error::custom)?;
     93        Ok(w.value)
     94    } else {
     95        Err(de::Error::custom("Cannot be deserialized to struct"))
     96    }
     97 }
     98 
     99 #[cfg(test)]
    100 mod tests {
    101    use super::*;
    102    use crate::test::{assert_de, assert_ser_de, ELEMENT_KEY};
    103    use serde_json::json;
    104 
    105    #[test]
    106    fn test_boolean_response() {
    107        assert_ser_de(&MarionetteResult::Bool(true), json!({"value": true}));
    108    }
    109 
    110    #[test]
    111    fn test_cookies_response() {
    112        let mut data = Vec::new();
    113        data.push(Cookie {
    114            name: "foo".into(),
    115            value: "bar".into(),
    116            path: Some("/common".into()),
    117            domain: Some("web-platform.test".into()),
    118            secure: false,
    119            http_only: false,
    120            expiry: None,
    121            same_site: Some("Strict".into()),
    122        });
    123        assert_ser_de(
    124            &MarionetteResult::Cookies(data),
    125            json!([{"name":"foo","value":"bar","path":"/common","domain":"web-platform.test","secure":false,"httpOnly":false,"sameSite":"Strict"}]),
    126        );
    127    }
    128 
    129    #[test]
    130    fn test_new_window_response() {
    131        let data = NewWindow {
    132            handle: "6442450945".into(),
    133            type_hint: "tab".into(),
    134        };
    135        let json = json!({"handle": "6442450945", "type": "tab"});
    136        assert_ser_de(&MarionetteResult::NewWindow(data), json);
    137    }
    138 
    139    #[test]
    140    fn test_web_element_response() {
    141        let data = WebElement {
    142            element: "foo".into(),
    143        };
    144        assert_ser_de(
    145            &MarionetteResult::WebElement(data),
    146            json!({"value": {ELEMENT_KEY: "foo"}}),
    147        );
    148    }
    149 
    150    #[test]
    151    fn test_web_elements_response() {
    152        let data = vec![
    153            WebElement {
    154                element: "foo".into(),
    155            },
    156            WebElement {
    157                element: "bar".into(),
    158            },
    159        ];
    160        assert_ser_de(
    161            &MarionetteResult::WebElements(data),
    162            json!([{ELEMENT_KEY: "foo"}, {ELEMENT_KEY: "bar"}]),
    163        );
    164    }
    165 
    166    #[test]
    167    fn test_timeouts_response() {
    168        let data = Timeouts {
    169            implicit: Some(1000),
    170            page_load: Some(200000),
    171            script: Some(Some(60000)),
    172        };
    173        assert_ser_de(
    174            &MarionetteResult::Timeouts(data),
    175            json!({"implicit":1000,"pageLoad":200000,"script":60000}),
    176        );
    177    }
    178 
    179    #[test]
    180    fn test_string_response() {
    181        assert_ser_de(
    182            &MarionetteResult::String("foo".into()),
    183            json!({"value": "foo"}),
    184        );
    185    }
    186 
    187    #[test]
    188    fn test_strings_response() {
    189        assert_ser_de(
    190            &MarionetteResult::Strings(vec!["2147483649".to_string()]),
    191            json!(["2147483649"]),
    192        );
    193    }
    194 
    195    #[test]
    196    fn test_null_response() {
    197        assert_ser_de(&MarionetteResult::Null, json!({ "value": null }));
    198    }
    199 
    200    #[test]
    201    fn test_window_rect_response() {
    202        let data = WindowRect {
    203            x: 100,
    204            y: 100,
    205            width: 800,
    206            height: 600,
    207        };
    208        let json = json!({"x": 100, "y": 100, "width": 800, "height": 600});
    209        assert_ser_de(&MarionetteResult::WindowRect(data), json);
    210    }
    211 
    212    #[test]
    213    fn test_element_rect_response() {
    214        let data = ElementRect {
    215            x: 8.0,
    216            y: 8.0,
    217            width: 148.6666717529297,
    218            height: 22.0,
    219        };
    220        let json = json!({"x": 8, "y": 8, "width": 148.6666717529297, "height": 22});
    221        assert_de(&MarionetteResult::ElementRect(data), json);
    222    }
    223 }