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