Skip to main content

servoshell/desktop/protocols/
servo.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
5//! Loads resources using a mapping from well-known shortcuts to resource: urls.
6//! Recognized shortcuts:
7//! - servo:default-user-agent
8//! - servo:experimental-preferences
9//! - servo:config
10//! - servo:newtab
11//! - servo:preferences
12
13use std::future::Future;
14use std::pin::Pin;
15
16use headers::{ContentType, HeaderMapExt};
17use servo::UserAgentPlatform;
18use servo::protocol_handler::{
19    DoneChannel, FetchContext, NetworkError, ProtocolHandler, Request, ResourceFetchTiming,
20    Response, ResponseBody,
21};
22
23use crate::desktop::protocols::resource::ResourceProtocolHandler;
24use crate::prefs::EXPERIMENTAL_PREFS;
25
26#[derive(Default)]
27pub struct ServoProtocolHandler {}
28
29impl ProtocolHandler for ServoProtocolHandler {
30    fn privileged_paths(&self) -> &'static [&'static str] {
31        &["config", "preferences"]
32    }
33
34    fn is_fetchable(&self) -> bool {
35        true
36    }
37
38    fn load(
39        &self,
40        request: &mut Request,
41        done_chan: &mut DoneChannel,
42        context: &FetchContext,
43    ) -> Pin<Box<dyn Future<Output = Response> + Send>> {
44        let url = request.current_url();
45
46        match url.path() {
47            "config" => ResourceProtocolHandler::response_for_path(
48                request,
49                done_chan,
50                context,
51                "/config.html",
52            ),
53            "newtab" => ResourceProtocolHandler::response_for_path(
54                request,
55                done_chan,
56                context,
57                "/newtab.html",
58            ),
59
60            "preferences" => ResourceProtocolHandler::response_for_path(
61                request,
62                done_chan,
63                context,
64                "/preferences.html",
65            ),
66
67            "license" => ResourceProtocolHandler::response_for_path(
68                request,
69                done_chan,
70                context,
71                "/license.html",
72            ),
73
74            "experimental-preferences" => {
75                let pref_list = EXPERIMENTAL_PREFS
76                    .iter()
77                    .map(|pref| format!("\"{pref}\""))
78                    .collect::<Vec<String>>()
79                    .join(",");
80                json_response(request, format!("[{pref_list}]"))
81            },
82
83            "default-user-agent" => {
84                let user_agent = UserAgentPlatform::default().to_user_agent_string();
85                json_response(request, format!("\"{user_agent}\""))
86            },
87
88            _ => Box::pin(std::future::ready(Response::network_error(
89                NetworkError::ResourceLoadError("Invalid shortcut".to_owned()),
90            ))),
91        }
92    }
93}
94
95fn json_response(
96    request: &Request,
97    body: String,
98) -> Pin<Box<dyn Future<Output = Response> + Send>> {
99    let mut response = Response::new(
100        request.current_url(),
101        ResourceFetchTiming::new(request.timing_type()),
102    );
103    response.headers.typed_insert(ContentType::json());
104    *response.body.lock() = ResponseBody::Done(body.into_bytes());
105    Box::pin(std::future::ready(response))
106}