Skip to main content

devtools/actors/
device.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 https://mozilla.org/MPL/2.0/. */
4
5use std::sync::Arc;
6
7use malloc_size_of_derive::MallocSizeOf;
8use serde::Serialize;
9use serde_json::{Map, Value};
10
11use crate::StreamId;
12use crate::actor::{Actor, ActorError, ActorRegistry, new_actor_name};
13use crate::protocol::{ActorDescription, ClientRequest, Method};
14
15#[derive(Serialize)]
16struct GetDescriptionReply {
17    from: String,
18    value: SystemInfo,
19}
20
21// This is only a minimal subset of the properties exposed/expected by Firefox
22// (see https://searchfox.org/mozilla-central/source/devtools/shared/system.js#45)
23#[derive(Serialize)]
24#[serde(rename_all = "camelCase")]
25struct SystemInfo {
26    apptype: String,
27    // Display version
28    version: String,
29    // Build ID (timestamp with format YYYYMMDDhhmmss), used for compatibility checks
30    // (see https://searchfox.org/mozilla-central/source/devtools/client/shared/remote-debugging/version-checker.js#82)
31    appbuildid: String,
32    // Firefox major.minor version number, use for compatibility checks
33    platformversion: String,
34    // Display name
35    brand_name: String,
36}
37
38include!(concat!(env!("OUT_DIR"), "/build_id.rs"));
39
40#[derive(MallocSizeOf)]
41pub(crate) struct DeviceActor {
42    name: String,
43}
44
45impl Actor for DeviceActor {
46    fn name(&self) -> &str {
47        &self.name
48    }
49    fn handle_message(
50        &self,
51        request: ClientRequest,
52        _registry: &ActorRegistry,
53        msg_type: &str,
54        _msg: &Map<String, Value>,
55        _id: StreamId,
56    ) -> Result<(), ActorError> {
57        match msg_type {
58            "getDescription" => {
59                let msg = GetDescriptionReply {
60                    from: self.name().into(),
61                    value: SystemInfo {
62                        apptype: "servo".to_string(),
63                        version: env!("CARGO_PKG_VERSION").to_string(),
64                        appbuildid: BUILD_ID.to_string(),
65                        platformversion: "157.0".to_string(),
66                        brand_name: "Servo".to_string(),
67                    },
68                };
69                request.reply_final(&msg)?
70            },
71
72            _ => return Err(ActorError::UnrecognizedPacketType),
73        };
74        Ok(())
75    }
76}
77
78impl DeviceActor {
79    pub fn register(registry: &ActorRegistry) -> Arc<Self> {
80        let name = new_actor_name::<Self>();
81        let actor = DeviceActor { name };
82        registry.register::<Self>(actor)
83    }
84
85    pub fn description() -> ActorDescription {
86        ActorDescription {
87            category: "actor",
88            type_name: "device",
89            methods: vec![Method {
90                name: "getDescription",
91                request: Value::Null,
92                response: Value::Object(
93                    vec![(
94                        "value".to_owned(),
95                        Value::Object(
96                            vec![("_retval".to_owned(), Value::String("json".to_owned()))]
97                                .into_iter()
98                                .collect(),
99                        ),
100                    )]
101                    .into_iter()
102                    .collect(),
103                ),
104            }],
105        }
106    }
107}