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 net::fetch::methods::{DoneChannel, FetchContext};
17use net::protocols::ProtocolHandler;
18use net_traits::ResourceFetchTiming;
19use net_traits::request::Request;
20use net_traits::response::{Response, ResponseBody};
21use servo::config::prefs::UserAgentPlatform;
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        &["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            "newtab" => ResourceProtocolHandler::response_for_path(
48                request,
49                done_chan,
50                context,
51                "/newtab.html",
52            ),
53
54            "preferences" => ResourceProtocolHandler::response_for_path(
55                request,
56                done_chan,
57                context,
58                "/preferences.html",
59            ),
60
61            "experimental-preferences" => {
62                let pref_list = EXPERIMENTAL_PREFS
63                    .iter()
64                    .map(|pref| format!("\"{pref}\""))
65                    .collect::<Vec<String>>()
66                    .join(",");
67                json_response(request, format!("[{pref_list}]"))
68            },
69
70            "default-user-agent" => {
71                let user_agent = UserAgentPlatform::default().to_user_agent_string();
72                json_response(request, format!("\"{user_agent}\""))
73            },
74
75            _ => Box::pin(std::future::ready(Response::network_internal_error(
76                "Invalid shortcut",
77            ))),
78        }
79    }
80}
81
82fn json_response(
83    request: &Request,
84    body: String,
85) -> Pin<Box<dyn Future<Output = Response> + Send>> {
86    let mut response = Response::new(
87        request.current_url(),
88        ResourceFetchTiming::new(request.timing_type()),
89    );
90    response.headers.typed_insert(ContentType::json());
91    *response.body.lock().unwrap() = ResponseBody::Done(body.into_bytes());
92    Box::pin(std::future::ready(response))
93}