embedder_traits/
resources.rs1use std::path::PathBuf;
6use std::sync::RwLock;
7
8static RES: RwLock<Option<Box<dyn ResourceReaderMethods + Sync + Send>>> = RwLock::new(None);
9
10#[cfg(feature = "baked-default-resources")]
11static INIT_TEST_RESOURCES: std::sync::Once = std::sync::Once::new();
12
13#[cfg(all(feature = "baked-default-resources", servo_production))]
14const _: () = assert!(
15 false,
16 "baked-default-resources should not be used in production"
17);
18
19pub fn set(reader: Box<dyn ResourceReaderMethods + Sync + Send>) {
21 *RES.write().unwrap() = Some(reader);
22}
23
24#[cfg(not(feature = "baked-default-resources"))]
25pub fn read_bytes(res: Resource) -> Vec<u8> {
26 if let Some(reader) = RES.read().unwrap().as_ref() {
27 reader.read(res)
28 } else {
29 log::error!("Resource reader not set.");
30 vec![]
31 }
32}
33
34#[cfg(feature = "baked-default-resources")]
35pub fn read_bytes(res: Resource) -> Vec<u8> {
36 INIT_TEST_RESOURCES.call_once(|| {
37 let mut reader = RES.write().unwrap();
38 if reader.is_none() {
39 *reader = Some(resources_for_tests())
40 }
41 });
42 RES.read()
43 .unwrap()
44 .as_ref()
45 .expect("Resource reader not set.")
46 .read(res)
47}
48
49pub fn read_string(res: Resource) -> String {
50 String::from_utf8(read_bytes(res)).unwrap()
51}
52
53pub fn sandbox_access_files() -> Vec<PathBuf> {
54 RES.read()
55 .unwrap()
56 .as_ref()
57 .map(|reader| reader.sandbox_access_files())
58 .unwrap_or_default()
59}
60
61pub fn sandbox_access_files_dirs() -> Vec<PathBuf> {
62 RES.read()
63 .unwrap()
64 .as_ref()
65 .map(|reader| reader.sandbox_access_files_dirs())
66 .unwrap_or_default()
67}
68
69pub enum Resource {
70 BluetoothBlocklist,
75 DomainList,
81 HstsPreloadList,
84 BadCertHTML,
90 NetErrorHTML,
94 RippyPNG,
101 CrashHTML,
106 DirectoryListingHTML,
110 AboutMemoryHTML,
112 DebuggerJS,
114}
115
116impl Resource {
117 pub fn filename(&self) -> &'static str {
118 match self {
119 Resource::BluetoothBlocklist => "gatt_blocklist.txt",
120 Resource::DomainList => "public_domains.txt",
121 Resource::HstsPreloadList => "hsts_preload.fstmap",
122 Resource::BadCertHTML => "badcert.html",
123 Resource::NetErrorHTML => "neterror.html",
124 Resource::RippyPNG => "rippy.png",
125 Resource::CrashHTML => "crash.html",
126 Resource::DirectoryListingHTML => "directory-listing.html",
127 Resource::AboutMemoryHTML => "about-memory.html",
128 Resource::DebuggerJS => "debugger.js",
129 }
130 }
131}
132
133pub trait ResourceReaderMethods {
134 fn read(&self, res: Resource) -> Vec<u8>;
135 fn sandbox_access_files(&self) -> Vec<PathBuf>;
136 fn sandbox_access_files_dirs(&self) -> Vec<PathBuf>;
137}
138
139#[cfg(feature = "baked-default-resources")]
143fn resources_for_tests() -> Box<dyn ResourceReaderMethods + Sync + Send> {
144 struct ResourceReader;
145 impl ResourceReaderMethods for ResourceReader {
146 fn sandbox_access_files(&self) -> Vec<PathBuf> {
147 vec![]
148 }
149 fn sandbox_access_files_dirs(&self) -> Vec<PathBuf> {
150 vec![]
151 }
152 fn read(&self, file: Resource) -> Vec<u8> {
153 match file {
154 Resource::BluetoothBlocklist => {
155 &include_bytes!("../../../resources/gatt_blocklist.txt")[..]
156 },
157 Resource::DomainList => {
158 &include_bytes!("../../../resources/public_domains.txt")[..]
159 },
160 Resource::HstsPreloadList => {
161 &include_bytes!("../../../resources/hsts_preload.fstmap")[..]
162 },
163 Resource::BadCertHTML => &include_bytes!("../../../resources/badcert.html")[..],
164 Resource::NetErrorHTML => &include_bytes!("../../../resources/neterror.html")[..],
165 Resource::RippyPNG => &include_bytes!("../../../resources/rippy.png")[..],
166 Resource::CrashHTML => &include_bytes!("../../../resources/crash.html")[..],
167 Resource::DirectoryListingHTML => {
168 &include_bytes!("../../../resources/directory-listing.html")[..]
169 },
170 Resource::AboutMemoryHTML => {
171 &include_bytes!("../../../resources/about-memory.html")[..]
172 },
173 Resource::DebuggerJS => &include_bytes!("../../../resources/debugger.js")[..],
174 }
175 .to_owned()
176 }
177 }
178 Box::new(ResourceReader)
179}