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