1use html5ever::{interface::QualName, namespace_url, ns, LocalName};
6use kuchiki::{Attribute, ExpandedName, NodeRef};
7
8pub fn inject_invoke_key_token(document: &mut NodeRef) {
12 let mut targets = vec![];
13 if let Ok(scripts) = document.select("script") {
14 for target in scripts {
15 targets.push(target);
16 }
17 for target in targets {
18 let node = target.as_node();
19 let element = node.as_element().unwrap();
20
21 let attrs = element.attributes.borrow();
22 if attrs.get("src").is_some() {
24 continue;
25 }
26
27 let replacement_node = match attrs.get("type") {
28 Some("module") | Some("application/ecmascript") => {
29 let replacement_node = NodeRef::new_element(
30 QualName::new(None, ns!(html), "script".into()),
31 element
32 .attributes
33 .borrow()
34 .clone()
35 .map
36 .into_iter()
37 .collect::<Vec<_>>(),
38 );
39 let script = node.text_contents();
40 replacement_node.append(NodeRef::new_text(format!(
41 r#"
42 const __TAURI_INVOKE_KEY__ = __TAURI__INVOKE_KEY_TOKEN__;
43 {}
44 "#,
45 script
46 )));
47 replacement_node
48 }
49 Some("application/javascript") | None => {
50 let replacement_node = NodeRef::new_element(
51 QualName::new(None, ns!(html), "script".into()),
52 element
53 .attributes
54 .borrow()
55 .clone()
56 .map
57 .into_iter()
58 .collect::<Vec<_>>(),
59 );
60 let script = node.text_contents();
61 replacement_node.append(NodeRef::new_text(
62 script.replace("__TAURI_INVOKE_KEY__", "__TAURI__INVOKE_KEY_TOKEN__"),
63 ));
64 replacement_node
65 }
66 _ => {
67 continue;
68 }
69 };
70
71 node.insert_after(replacement_node);
72 node.detach();
73 }
74 }
75}
76
77pub fn inject_csp(document: &mut NodeRef, csp: &str) {
79 if let Ok(ref head) = document.select_first("head") {
80 head.as_node().append(create_csp_meta_tag(csp));
81 } else {
82 let head = NodeRef::new_element(
83 QualName::new(None, ns!(html), LocalName::from("head")),
84 None,
85 );
86 head.append(create_csp_meta_tag(csp));
87 document.prepend(head);
88 }
89}
90
91fn create_csp_meta_tag(csp: &str) -> NodeRef {
92 NodeRef::new_element(
93 QualName::new(None, ns!(html), LocalName::from("meta")),
94 vec![
95 (
96 ExpandedName::new(ns!(), LocalName::from("http-equiv")),
97 Attribute {
98 prefix: None,
99 value: "Content-Security-Policy".into(),
100 },
101 ),
102 (
103 ExpandedName::new(ns!(), LocalName::from("content")),
104 Attribute {
105 prefix: None,
106 value: csp.into(),
107 },
108 ),
109 ],
110 )
111}
112
113#[cfg(test)]
114mod tests {
115 use kuchiki::traits::*;
116 #[test]
117 fn csp() {
118 let htmls = vec![
119 "<html><head></head></html>".to_string(),
120 "<html></html>".to_string(),
121 ];
122 for html in htmls {
123 let mut document = kuchiki::parse_html().one(html);
124 let csp = "default-src 'self'; img-src https://*; child-src 'none';";
125 super::inject_csp(&mut document, csp);
126 assert_eq!(
127 document.to_string(),
128 format!(
129 r#"<html><head><meta content="{}" http-equiv="Content-Security-Policy"></head><body></body></html>"#,
130 csp
131 )
132 );
133 }
134 }
135}