servoshell/desktop/protocols/
servo.rs1use 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}