aboutsummaryrefslogtreecommitdiffstats
path: root/components/shared/embedder/resources.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/shared/embedder/resources.rs')
-rw-r--r--components/shared/embedder/resources.rs154
1 files changed, 154 insertions, 0 deletions
diff --git a/components/shared/embedder/resources.rs b/components/shared/embedder/resources.rs
new file mode 100644
index 00000000000..fd1f44ff455
--- /dev/null
+++ b/components/shared/embedder/resources.rs
@@ -0,0 +1,154 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use std::path::PathBuf;
+use std::sync::RwLock;
+
+use cfg_if::cfg_if;
+use lazy_static::lazy_static;
+
+lazy_static! {
+ static ref RES: RwLock<Option<Box<dyn ResourceReaderMethods + Sync + Send>>> = {
+ cfg_if! {
+ if #[cfg(servo_production)] {
+ RwLock::new(None)
+ } else {
+ // Static assert that this is really a non-production build, rather
+ // than a failure of the build script’s production check.
+ const _: () = assert!(cfg!(servo_do_not_use_in_production));
+
+ RwLock::new(Some(resources_for_tests()))
+ }
+ }
+ };
+}
+
+pub fn set(reader: Box<dyn ResourceReaderMethods + Sync + Send>) {
+ *RES.write().unwrap() = Some(reader);
+}
+
+pub fn read_bytes(res: Resource) -> Vec<u8> {
+ RES.read()
+ .unwrap()
+ .as_ref()
+ .expect("Resource reader not set.")
+ .read(res)
+}
+
+pub fn read_string(res: Resource) -> String {
+ String::from_utf8(read_bytes(res)).unwrap()
+}
+
+pub fn sandbox_access_files() -> Vec<PathBuf> {
+ RES.read()
+ .unwrap()
+ .as_ref()
+ .expect("Resource reader not set.")
+ .sandbox_access_files()
+}
+
+pub fn sandbox_access_files_dirs() -> Vec<PathBuf> {
+ RES.read()
+ .unwrap()
+ .as_ref()
+ .expect("Resource reader not set.")
+ .sandbox_access_files_dirs()
+}
+
+pub enum Resource {
+ Preferences,
+ BluetoothBlocklist,
+ DomainList,
+ HstsPreloadList,
+ BadCertHTML,
+ NetErrorHTML,
+ UserAgentCSS,
+ ServoCSS,
+ PresentationalHintsCSS,
+ QuirksModeCSS,
+ RippyPNG,
+ MediaControlsCSS,
+ MediaControlsJS,
+ CrashHTML,
+}
+
+impl Resource {
+ pub fn filename(&self) -> &'static str {
+ match self {
+ Resource::Preferences => "prefs.json",
+ Resource::BluetoothBlocklist => "gatt_blocklist.txt",
+ Resource::DomainList => "public_domains.txt",
+ Resource::HstsPreloadList => "hsts_preload.json",
+ Resource::BadCertHTML => "badcert.html",
+ Resource::NetErrorHTML => "neterror.html",
+ Resource::UserAgentCSS => "user-agent.css",
+ Resource::ServoCSS => "servo.css",
+ Resource::PresentationalHintsCSS => "presentational-hints.css",
+ Resource::QuirksModeCSS => "quirks-mode.css",
+ Resource::RippyPNG => "rippy.png",
+ Resource::MediaControlsCSS => "media-controls.css",
+ Resource::MediaControlsJS => "media-controls.js",
+ Resource::CrashHTML => "crash.html",
+ }
+ }
+}
+
+pub trait ResourceReaderMethods {
+ fn read(&self, res: Resource) -> Vec<u8>;
+ fn sandbox_access_files(&self) -> Vec<PathBuf>;
+ fn sandbox_access_files_dirs(&self) -> Vec<PathBuf>;
+}
+
+/// Bake all of our resources into this crate for tests, unless we are `cfg!(servo_production)`.
+///
+/// Local non-production embedder builds (e.g. servoshell) can still override these with [`set`],
+/// if runtime loading of prefs.json and other resources is needed.
+///
+/// In theory this can be `#[cfg(servo_production)]`, but omitting the attribute ensures that the
+/// code is always checked by the compiler, even if it later gets optimised out as dead code.
+fn resources_for_tests() -> Box<dyn ResourceReaderMethods + Sync + Send> {
+ struct ResourceReader;
+ impl ResourceReaderMethods for ResourceReader {
+ fn sandbox_access_files(&self) -> Vec<PathBuf> {
+ vec![]
+ }
+ fn sandbox_access_files_dirs(&self) -> Vec<PathBuf> {
+ vec![]
+ }
+ fn read(&self, file: Resource) -> Vec<u8> {
+ match file {
+ Resource::Preferences => &include_bytes!("../../../resources/prefs.json")[..],
+ Resource::BluetoothBlocklist => {
+ &include_bytes!("../../../resources/gatt_blocklist.txt")[..]
+ },
+ Resource::DomainList => {
+ &include_bytes!("../../../resources/public_domains.txt")[..]
+ },
+ Resource::HstsPreloadList => {
+ &include_bytes!("../../../resources/hsts_preload.json")[..]
+ },
+ Resource::BadCertHTML => &include_bytes!("../../../resources/badcert.html")[..],
+ Resource::NetErrorHTML => &include_bytes!("../../../resources/neterror.html")[..],
+ Resource::UserAgentCSS => &include_bytes!("../../../resources/user-agent.css")[..],
+ Resource::ServoCSS => &include_bytes!("../../../resources/servo.css")[..],
+ Resource::PresentationalHintsCSS => {
+ &include_bytes!("../../../resources/presentational-hints.css")[..]
+ },
+ Resource::QuirksModeCSS => {
+ &include_bytes!("../../../resources/quirks-mode.css")[..]
+ },
+ Resource::RippyPNG => &include_bytes!("../../../resources/rippy.png")[..],
+ Resource::MediaControlsCSS => {
+ &include_bytes!("../../../resources/media-controls.css")[..]
+ },
+ Resource::MediaControlsJS => {
+ &include_bytes!("../../../resources/media-controls.js")[..]
+ },
+ Resource::CrashHTML => &include_bytes!("../../../resources/crash.html")[..],
+ }
+ .to_owned()
+ }
+ }
+ Box::new(ResourceReader)
+}