diff --git a/Cargo.lock b/Cargo.lock index 6cd233c611c..d8b30bb82dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1601,6 +1601,7 @@ dependencies = [ "servo_config", "servo_rand", "servo_url", + "storage_traits", "stylo", "stylo_traits", "tracing", @@ -1636,6 +1637,7 @@ dependencies = [ "servo_config", "servo_malloc_size_of", "servo_url", + "storage_traits", "strum", "strum_macros", "stylo_traits", @@ -5054,6 +5056,8 @@ dependencies = [ "servo_config", "servo_geometry", "servo_url", + "storage", + "storage_traits", "stylo", "stylo_traits", "surfman", @@ -5529,7 +5533,6 @@ dependencies = [ "async-tungstenite", "base", "base64 0.22.1", - "bincode", "bytes", "chrono", "compositing_traits", @@ -5565,13 +5568,10 @@ dependencies = [ "profile_traits", "rayon", "resvg", - "rusqlite", "rustc-hash 2.1.1", "rustls", "rustls-pemfile", "rustls-pki-types", - "sea-query", - "sea-query-rusqlite", "serde", "serde_json", "servo_arc", @@ -5579,7 +5579,6 @@ dependencies = [ "servo_malloc_size_of", "servo_url", "sha2", - "tempfile", "time", "tokio", "tokio-rustls", @@ -7397,6 +7396,7 @@ dependencies = [ "servo_rand", "servo_url", "smallvec", + "storage_traits", "strum", "strum_macros", "stylo", @@ -7501,6 +7501,7 @@ dependencies = [ "servo_config", "servo_malloc_size_of", "servo_url", + "storage_traits", "strum", "strum_macros", "stylo_atoms", @@ -8274,6 +8275,47 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "storage" +version = "0.0.1" +dependencies = [ + "base", + "bincode", + "ipc-channel", + "log", + "malloc_size_of_derive", + "profile_traits", + "rusqlite", + "rustc-hash 2.1.1", + "sea-query", + "sea-query-rusqlite", + "serde", + "serde_json", + "servo_config", + "servo_malloc_size_of", + "servo_url", + "storage_traits", + "tempfile", + "tokio", + "tokio-rustls", + "tokio-stream", + "tokio-util", + "uuid", +] + +[[package]] +name = "storage_traits" +version = "0.0.1" +dependencies = [ + "base", + "ipc-channel", + "malloc_size_of_derive", + "profile_traits", + "serde", + "servo_malloc_size_of", + "servo_url", +] + [[package]] name = "strck" version = "0.1.2" diff --git a/Cargo.toml b/Cargo.toml index 170a62c8f9c..dd40b2cf451 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -140,6 +140,7 @@ servo-tracing = { path = "components/servo_tracing" } servo_arc = { git = "https://github.com/servo/stylo", branch = "2025-09-02" } skrifa = "0.35.0" smallvec = { version = "1.15", features = ["serde", "union"] } +storage_traits = { path = "components/shared/storage" } string_cache = "0.8" strum = "0.26" strum_macros = "0.26" diff --git a/components/constellation/Cargo.toml b/components/constellation/Cargo.toml index 5a212acc600..ad2d66f03d9 100644 --- a/components/constellation/Cargo.toml +++ b/components/constellation/Cargo.toml @@ -55,6 +55,7 @@ servo-tracing = { workspace = true } servo_config = { path = "../config" } servo_rand = { path = "../rand" } servo_url = { path = "../url" } +storage_traits = { workspace = true } stylo = { workspace = true } stylo_traits = { workspace = true } tracing = { workspace = true, optional = true } diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 888d18ef65b..c4594cc6fb3 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -151,7 +151,6 @@ use net::image_cache::ImageCacheImpl; use net_traits::image_cache::ImageCache; use net_traits::pub_domains::reg_host; use net_traits::request::Referrer; -use net_traits::storage_thread::{StorageThreadMsg, StorageType}; use net_traits::{ self, AsyncRuntime, ReferrerPolicy, ResourceThreads, exit_fetch_thread, start_fetch_thread, }; @@ -167,6 +166,8 @@ use servo_config::prefs::{self, PrefValue}; use servo_config::{opts, pref}; use servo_rand::{Rng, ServoRng, SliceRandom, random}; use servo_url::{Host, ImmutableOrigin, ServoUrl}; +use storage_traits::StorageThreads; +use storage_traits::storage_thread::{StorageThreadMsg, StorageType}; use style::global_style_data::StyleThreadPool; #[cfg(feature = "webgpu")] use webgpu::canvas_context::WGPUImageMap; @@ -347,6 +348,17 @@ pub struct Constellation { /// browsing. private_resource_threads: ResourceThreads, + /// Channels for the constellation to send messages to the public + /// storage-related threads. There are two groups of storage threads: one + /// for public browsing, and one for private browsing. + public_storage_threads: StorageThreads, + + /// Channels for the constellation to send messages to the private + /// storage-related threads. There are two groups of storage + /// threads: one for public browsing, and one for private + /// browsing. + private_storage_threads: StorageThreads, + /// A channel for the constellation to send messages to the font /// cache thread. system_font_service: Arc, @@ -520,6 +532,12 @@ pub struct InitialConstellationState { /// A channel to the resource thread. pub private_resource_threads: ResourceThreads, + /// A channel to the storage thread. + pub public_storage_threads: StorageThreads, + + /// A channel to the storage thread. + pub private_storage_threads: StorageThreads, + /// A channel to the time profiler thread. pub time_profiler_chan: time::ProfilerChan, @@ -697,6 +715,8 @@ where bluetooth_ipc_sender: state.bluetooth_thread, public_resource_threads: state.public_resource_threads, private_resource_threads: state.private_resource_threads, + public_storage_threads: state.public_storage_threads, + private_storage_threads: state.private_storage_threads, system_font_service: state.system_font_service, sw_managers: Default::default(), swmanager_receiver, @@ -979,6 +999,11 @@ where } else { self.public_resource_threads.clone() }; + let storage_threads = if is_private { + self.private_storage_threads.clone() + } else { + self.public_storage_threads.clone() + }; let embedder_chan = self.embedder_proxy.sender.clone(); let eventloop_waker = self.embedder_proxy.event_loop_waker.clone(); @@ -1009,6 +1034,7 @@ where swmanager_thread: self.swmanager_ipc_sender.clone(), system_font_service: self.system_font_service.clone(), resource_threads, + storage_threads, time_profiler_chan: self.time_profiler_chan.clone(), mem_profiler_chan: self.mem_profiler_chan.clone(), viewport_details: initial_viewport_details, @@ -2676,7 +2702,7 @@ where debug!("Exiting storage resource threads."); if let Err(e) = generic_channel::GenericSend::send( - &self.public_resource_threads, + &self.public_storage_threads, StorageThreadMsg::Exit(storage_ipc_sender), ) { warn!("Exit storage thread failed ({})", e); diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index 07685d95248..17876523301 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -51,6 +51,7 @@ use serde::{Deserialize, Serialize}; use servo_config::opts::{self, Opts}; use servo_config::prefs::{self, Preferences}; use servo_url::ServoUrl; +use storage_traits::StorageThreads; use crate::event_loop::EventLoop; use crate::process_manager::Process; @@ -168,6 +169,9 @@ pub struct InitialPipelineState { /// Channels to the resource-related threads. pub resource_threads: ResourceThreads, + /// Channels to the storage-related threads. + pub storage_threads: StorageThreads, + /// A channel to the time profiler thread. pub time_profiler_chan: time::ProfilerChan, @@ -297,6 +301,7 @@ impl Pipeline { swmanager_thread: state.swmanager_thread, system_font_service: state.system_font_service.to_sender(), resource_threads: state.resource_threads, + storage_threads: state.storage_threads, time_profiler_chan: state.time_profiler_chan, mem_profiler_chan: state.mem_profiler_chan, viewport_details: state.viewport_details, @@ -495,6 +500,7 @@ pub struct UnprivilegedPipelineContent { swmanager_thread: GenericSender, system_font_service: SystemFontServiceProxySender, resource_threads: ResourceThreads, + storage_threads: StorageThreads, time_profiler_chan: time::ProfilerChan, mem_profiler_chan: profile_mem::ProfilerChan, viewport_details: ViewportDetails, @@ -551,6 +557,7 @@ impl UnprivilegedPipelineContent { #[cfg(feature = "bluetooth")] bluetooth_sender: self.bluetooth_thread, resource_threads: self.resource_threads, + storage_threads: self.storage_threads, image_cache, time_profiler_sender: self.time_profiler_chan.clone(), memory_profiler_sender: self.mem_profiler_chan.clone(), diff --git a/components/fonts/tests/font_context.rs b/components/fonts/tests/font_context.rs index 8b78cf60df6..b25f59bf86e 100644 --- a/components/fonts/tests/font_context.rs +++ b/components/fonts/tests/font_context.rs @@ -49,10 +49,7 @@ mod font_context { fn new() -> TestContext { let (system_font_service, system_font_service_proxy) = MockSystemFontService::spawn(); let (core_sender, _) = ipc::channel().unwrap(); - let (storage_sender, _) = generic_channel::channel().unwrap(); - let (indexeddb_sender, _) = ipc::channel().unwrap(); - let mock_resource_threads = - ResourceThreads::new(core_sender, storage_sender, indexeddb_sender); + let mock_resource_threads = ResourceThreads::new(core_sender); let mock_compositor_api = CrossProcessCompositorApi::dummy(); let proxy_clone = Arc::new(system_font_service_proxy.to_sender().to_proxy()); diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml index 404c8e8a260..3d2eb3c7594 100644 --- a/components/net/Cargo.toml +++ b/components/net/Cargo.toml @@ -20,7 +20,6 @@ async-recursion = "1.1" async-tungstenite = { workspace = true } base = { workspace = true } base64 = { workspace = true } -bincode = { workspace = true } bytes = "1" chrono = { workspace = true } compositing_traits = { workspace = true } @@ -56,13 +55,10 @@ pixels = { path = "../pixels" } profile_traits = { workspace = true } rayon = { workspace = true } resvg = { workspace = true } -rusqlite = { version = "0.37", features = ["bundled"] } rustc-hash = { workspace = true } rustls = { workspace = true } rustls-pemfile = { workspace = true } rustls-pki-types = { workspace = true } -sea-query = { version = "1.0.0-rc.9", default-features = false, features = ["backend-sqlite", "derive"] } -sea-query-rusqlite = { version = "0.8.0-rc.8" } serde = { workspace = true } serde_json = { workspace = true } servo_arc = { workspace = true } @@ -89,7 +85,6 @@ futures = { version = "0.3", features = ["compat"] } hyper = { workspace = true, features = ["full"] } hyper-util = { workspace = true, features = ["server-graceful"] } rustls = { workspace = true, features = ["aws-lc-rs"] } -tempfile = "3" [[test]] name = "main" diff --git a/components/net/filemanager_thread.rs b/components/net/filemanager_thread.rs index e4045db2adc..27c7f953931 100644 --- a/components/net/filemanager_thread.rs +++ b/components/net/filemanager_thread.rs @@ -11,6 +11,7 @@ use std::sync::{Arc, Mutex, RwLock, Weak}; use base::generic_channel; use base::id::WebViewId; +use base::threadpool::ThreadPool; use embedder_traits::{EmbedderMsg, EmbedderProxy, FilterPattern}; use headers::{ContentLength, ContentRange, ContentType, HeaderMap, HeaderMapExt, Range}; use http::header::{self, HeaderValue}; @@ -33,7 +34,6 @@ use uuid::Uuid; use crate::fetch::methods::{CancellationListener, Data, RangeRequestBounds}; use crate::protocols::get_range_request_bounds; -use crate::resource_thread::CoreResourceThreadPool; pub const FILE_CHUNK_SIZE: usize = 32768; // 32 KB @@ -79,14 +79,11 @@ enum FileImpl { pub struct FileManager { embedder_proxy: EmbedderProxy, store: Arc, - thread_pool: Weak, + thread_pool: Weak, } impl FileManager { - pub fn new( - embedder_proxy: EmbedderProxy, - pool_handle: Weak, - ) -> FileManager { + pub fn new(embedder_proxy: EmbedderProxy, pool_handle: Weak) -> FileManager { FileManager { embedder_proxy, store: Arc::new(FileManagerStore::new()), diff --git a/components/net/image_cache.rs b/components/net/image_cache.rs index 9874d25b210..ec35c2e5c2e 100644 --- a/components/net/image_cache.rs +++ b/components/net/image_cache.rs @@ -9,6 +9,7 @@ use std::sync::{Arc, Mutex}; use std::{mem, thread}; use base::id::PipelineId; +use base::threadpool::ThreadPool; use compositing_traits::{CrossProcessCompositorApi, ImageUpdate, SerializableImageData}; use imsz::imsz_from_reader; use ipc_channel::ipc::{IpcSender, IpcSharedMemory}; @@ -35,8 +36,6 @@ use webrender_api::{ ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey as WebRenderImageKey, }; -use crate::resource_thread::CoreResourceThreadPool; - // We bake in rippy.png as a fallback, in case the embedder does not provide // a rippy resource. this version is 253 bytes large, don't exchange it against // something in higher resolution. @@ -703,7 +702,7 @@ pub struct ImageCacheImpl { store: Arc>, /// Thread pool for image decoding - thread_pool: Arc, + thread_pool: Arc, } impl ImageCache for ImageCacheImpl { @@ -730,10 +729,7 @@ impl ImageCache for ImageCacheImpl { pipeline_id: None, key_cache: KeyCache::new(), })), - thread_pool: Arc::new(CoreResourceThreadPool::new( - thread_count, - "ImageCache".to_string(), - )), + thread_pool: Arc::new(ThreadPool::new(thread_count, "ImageCache".to_string())), } } diff --git a/components/net/lib.rs b/components/net/lib.rs index caee5ae7791..e531021faf5 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -15,12 +15,10 @@ pub mod hsts; pub mod http_cache; pub mod http_loader; pub mod image_cache; -pub mod indexeddb; pub mod local_directory_listing; pub mod protocols; pub mod request_interceptor; pub mod resource_thread; -mod storage_thread; pub mod subresource_integrity; mod websocket_loader; diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index f356f4da673..4557a65bad9 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -11,10 +11,9 @@ use std::io::{self, BufReader}; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex, RwLock, Weak}; use std::thread; -use std::time::Duration; -use base::generic_channel::GenericSender; use base::id::CookieStoreId; +use base::threadpool::ThreadPool; use cookie::Cookie; use crossbeam_channel::Sender; use devtools_traits::DevtoolsControlMsg; @@ -24,11 +23,9 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcReceiverSet, IpcSender}; use log::{debug, warn}; use net_traits::blob_url_store::parse_blob_url; use net_traits::filemanager_thread::FileTokenCheck; -use net_traits::indexeddb_thread::IndexedDBThreadMsg; use net_traits::pub_domains::public_suffix_list_size_of; use net_traits::request::{Destination, RequestBuilder, RequestId}; use net_traits::response::{Response, ResponseInit}; -use net_traits::storage_thread::StorageThreadMsg; use net_traits::{ AsyncRuntime, CookieAsyncResponse, CookieData, CookieSource, CoreResourceMsg, CoreResourceThread, CustomResponseMediator, DiscardFetch, FetchChannels, FetchTaskTarget, @@ -60,10 +57,8 @@ use crate::filemanager_thread::FileManager; use crate::hsts::{self, HstsList}; use crate::http_cache::HttpCache; use crate::http_loader::{HttpState, http_redirect_fetch}; -use crate::indexeddb::idb_thread::IndexedDBThreadFactory; use crate::protocols::ProtocolRegistry; use crate::request_interceptor::RequestInterceptor; -use crate::storage_thread::StorageThreadFactory; use crate::websocket_loader; /// Load a file with CA certificate and produce a RootCertStore with the results. @@ -112,12 +107,9 @@ pub fn new_resource_threads( ignore_certificate_errors, protocols, ); - let idb: IpcSender = IndexedDBThreadFactory::new(config_dir.clone()); - let storage: GenericSender = - StorageThreadFactory::new(config_dir, mem_profiler_chan); ( - ResourceThreads::new(public_core, storage.clone(), idb.clone()), - ResourceThreads::new(private_core, storage, idb), + ResourceThreads::new(public_core), + ResourceThreads::new(private_core), async_runtime, ) } @@ -579,141 +571,11 @@ pub struct CoreResourceManager { sw_managers: HashMap>, filemanager: FileManager, request_interceptor: RequestInterceptor, - thread_pool: Arc, + thread_pool: Arc, ca_certificates: CACertificates, ignore_certificate_errors: bool, } -/// The state of the thread-pool used by CoreResource. -struct ThreadPoolState { - /// The number of active workers. - active_workers: u32, - /// Whether the pool can spawn additional work. - active: bool, -} - -impl ThreadPoolState { - pub fn new() -> ThreadPoolState { - ThreadPoolState { - active_workers: 0, - active: true, - } - } - - /// Is the pool still able to spawn new work? - pub fn is_active(&self) -> bool { - self.active - } - - /// How many workers are currently active? - pub fn active_workers(&self) -> u32 { - self.active_workers - } - - /// Prevent additional work from being spawned. - pub fn switch_to_inactive(&mut self) { - self.active = false; - } - - /// Add to the count of active workers. - pub fn increment_active(&mut self) { - self.active_workers += 1; - } - - /// Substract from the count of active workers. - pub fn decrement_active(&mut self) { - self.active_workers -= 1; - } -} - -/// Threadpool used by Fetch and file operations. -pub struct CoreResourceThreadPool { - pool: rayon::ThreadPool, - state: Arc>, -} - -impl CoreResourceThreadPool { - pub fn new(num_threads: usize, pool_name: String) -> CoreResourceThreadPool { - debug!("Creating new CoreResourceThreadPool with {num_threads} threads!"); - let pool = rayon::ThreadPoolBuilder::new() - .thread_name(move |i| format!("{pool_name}#{i}")) - .num_threads(num_threads) - .build() - .unwrap(); - let state = Arc::new(Mutex::new(ThreadPoolState::new())); - CoreResourceThreadPool { pool, state } - } - - /// Spawn work on the thread-pool, if still active. - /// - /// There is no need to give feedback to the caller, - /// because if we do not perform work, - /// it is because the system as a whole is exiting. - pub fn spawn(&self, work: OP) - where - OP: FnOnce() + Send + 'static, - { - { - let mut state = self.state.lock().unwrap(); - if state.is_active() { - state.increment_active(); - } else { - // Don't spawn any work. - return; - } - } - - let state = self.state.clone(); - - self.pool.spawn(move || { - { - let mut state = state.lock().unwrap(); - if !state.is_active() { - // Decrement number of active workers and return, - // without doing any work. - return state.decrement_active(); - } - } - // Perform work. - work(); - { - // Decrement number of active workers. - let mut state = state.lock().unwrap(); - state.decrement_active(); - } - }); - } - - /// Prevent further work from being spawned, - /// and wait until all workers are done, - /// or a timeout of roughly one second has been reached. - pub fn exit(&self) { - { - let mut state = self.state.lock().unwrap(); - state.switch_to_inactive(); - } - let mut rounds = 0; - loop { - rounds += 1; - { - let state = self.state.lock().unwrap(); - let still_active = state.active_workers(); - - if still_active == 0 || rounds == 10 { - if still_active > 0 { - debug!( - "Exiting CoreResourceThreadPool with {:?} still working(should be zero)", - still_active - ); - } - break; - } - } - thread::sleep(Duration::from_millis(100)); - } - } -} - impl CoreResourceManager { pub fn new( devtools_sender: Option>, @@ -726,7 +588,7 @@ impl CoreResourceManager { .map(|i| i.get()) .unwrap_or(servo_config::pref!(threadpools_fallback_worker_num) as usize) .min(servo_config::pref!(threadpools_resource_workers_max).max(1) as usize); - let pool = CoreResourceThreadPool::new(num_threads, "CoreResourceThreadPool".to_string()); + let pool = ThreadPool::new(num_threads, "CoreResourceThreadPool".to_string()); let pool_handle = Arc::new(pool); CoreResourceManager { devtools_sender, diff --git a/components/net/tests/fetch.rs b/components/net/tests/fetch.rs index 16cb1e30127..388ebb872f0 100644 --- a/components/net/tests/fetch.rs +++ b/components/net/tests/fetch.rs @@ -12,6 +12,7 @@ use std::sync::{Arc, Mutex, Weak}; use std::time::{Duration, SystemTime}; use base::id::{TEST_PIPELINE_ID, TEST_WEBVIEW_ID}; +use base::threadpool::ThreadPool; use content_security_policy as csp; use crossbeam_channel::{Sender, unbounded}; use devtools_traits::{HttpRequest as DevtoolsHttpRequest, HttpResponse as DevtoolsHttpResponse}; @@ -33,7 +34,6 @@ use net::filemanager_thread::FileManager; use net::hsts::HstsEntry; use net::protocols::ProtocolRegistry; use net::request_interceptor::RequestInterceptor; -use net::resource_thread::CoreResourceThreadPool; use net_traits::filemanager_thread::FileTokenCheck; use net_traits::http_status::HttpStatus; use net_traits::request::{ @@ -235,7 +235,7 @@ fn test_file() { .origin(url.origin()) .build(); - let pool = CoreResourceThreadPool::new(1, "CoreResourceTestPool".to_string()); + let pool = ThreadPool::new(1, "CoreResourceTestPool".to_string()); let pool_handle = Arc::new(pool); let mut context = new_fetch_context(None, None, Some(Arc::downgrade(&pool_handle))); let fetch_response = fetch_with_context(request, &mut context); diff --git a/components/net/tests/filemanager_thread.rs b/components/net/tests/filemanager_thread.rs index 7a3789c59f9..ab4613cca5b 100644 --- a/components/net/tests/filemanager_thread.rs +++ b/components/net/tests/filemanager_thread.rs @@ -8,10 +8,10 @@ use std::path::PathBuf; use std::sync::Arc; use base::id::TEST_WEBVIEW_ID; +use base::threadpool::ThreadPool; use embedder_traits::FilterPattern; use ipc_channel::ipc; use net::filemanager_thread::FileManager; -use net::resource_thread::CoreResourceThreadPool; use net_traits::blob_url_store::BlobURLStoreError; use net_traits::filemanager_thread::{ FileManagerThreadError, FileManagerThreadMsg, ReadFileProgress, @@ -26,7 +26,7 @@ fn test_filemanager() { preferences.dom_testing_html_input_element_select_files_enabled = true; servo_config::prefs::set(preferences); - let pool = CoreResourceThreadPool::new(1, "CoreResourceTestPool".to_string()); + let pool = ThreadPool::new(1, "CoreResourceTestPool".to_string()); let pool_handle = Arc::new(pool); let filemanager = FileManager::new(create_embedder_proxy(), Arc::downgrade(&pool_handle)); diff --git a/components/net/tests/main.rs b/components/net/tests/main.rs index 9f12a57092d..d6b745986c2 100644 --- a/components/net/tests/main.rs +++ b/components/net/tests/main.rs @@ -15,7 +15,6 @@ mod hsts; mod http_cache; mod http_loader; mod resource_thread; -mod sqlite; mod subresource_integrity; use core::convert::Infallible; @@ -26,6 +25,7 @@ use std::net::TcpListener as StdTcpListener; use std::path::{Path, PathBuf}; use std::sync::{Arc, LazyLock, Mutex, RwLock, Weak}; +use base::threadpool::ThreadPool; use content_security_policy as csp; use crossbeam_channel::{Receiver, Sender, unbounded}; use devtools_traits::DevtoolsControlMsg; @@ -45,7 +45,6 @@ use net::fetch::methods::{self, FetchContext}; use net::filemanager_thread::FileManager; use net::protocols::ProtocolRegistry; use net::request_interceptor::RequestInterceptor; -use net::resource_thread::CoreResourceThreadPool; use net::test::HttpState; use net_traits::filemanager_thread::FileTokenCheck; use net_traits::request::Request; @@ -163,7 +162,7 @@ fn create_http_state(fc: Option) -> HttpState { fn new_fetch_context( dc: Option>, fc: Option, - pool_handle: Option>, + pool_handle: Option>, ) -> FetchContext { let _ = &*ASYNC_RUNTIME; diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 2af39466c81..6fccbe40fea 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -116,6 +116,7 @@ servo_geometry = { path = "../geometry" } servo_rand = { path = "../rand" } servo_url = { path = "../url" } smallvec = { workspace = true } +storage_traits = { workspace = true } strum = { workspace = true } strum_macros = { workspace = true } stylo = { workspace = true } diff --git a/components/script/dom/debuggerglobalscope.rs b/components/script/dom/debuggerglobalscope.rs index c362f08616b..124d332b692 100644 --- a/components/script/dom/debuggerglobalscope.rs +++ b/components/script/dom/debuggerglobalscope.rs @@ -22,6 +22,7 @@ use script_bindings::codegen::GenericBindings::DebuggerGlobalScopeBinding::{ use script_bindings::realms::InRealm; use script_bindings::reflector::DomObject; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; +use storage_traits::StorageThreads; use crate::dom::bindings::codegen::Bindings::DebuggerGlobalScopeBinding; use crate::dom::bindings::error::report_pending_exception; @@ -68,6 +69,7 @@ impl DebuggerGlobalScope { script_to_constellation_chan: ScriptToConstellationChan, script_to_embedder_chan: ScriptToEmbedderChan, resource_threads: ResourceThreads, + storage_threads: StorageThreads, #[cfg(feature = "webgpu")] gpu_id_hub: std::sync::Arc, can_gc: CanGc, ) -> DomRoot { @@ -80,6 +82,7 @@ impl DebuggerGlobalScope { script_to_constellation_chan, script_to_embedder_chan, resource_threads, + storage_threads, MutableOrigin::new(ImmutableOrigin::new_opaque()), ServoUrl::parse_with_base(None, "about:internal/debugger") .expect("Guaranteed by argument"), diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index e330d3b154f..85ad4a92a56 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -441,6 +441,7 @@ impl DedicatedWorkerGlobalScope { init.script_to_constellation_chan.clone(), init.script_to_embedder_chan.clone(), init.resource_threads.clone(), + init.storage_threads.clone(), #[cfg(feature = "webgpu")] gpu_id_hub.clone(), CanGc::note(), diff --git a/components/script/dom/dissimilaroriginwindow.rs b/components/script/dom/dissimilaroriginwindow.rs index 881042286b9..6cfd910ced5 100644 --- a/components/script/dom/dissimilaroriginwindow.rs +++ b/components/script/dom/dissimilaroriginwindow.rs @@ -60,6 +60,7 @@ impl DissimilarOriginWindow { global_to_clone_from.script_to_constellation_chan().clone(), global_to_clone_from.script_to_embedder_chan().clone(), global_to_clone_from.resource_threads().clone(), + global_to_clone_from.storage_threads().clone(), global_to_clone_from.origin().clone(), global_to_clone_from.creation_url().clone(), global_to_clone_from.top_level_creation_url().clone(), diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index fa27108cf26..5f08d8a6efd 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -60,6 +60,7 @@ use profile_traits::{ipc as profile_ipc, mem as profile_mem, time as profile_tim use rustc_hash::{FxBuildHasher, FxHashMap}; use script_bindings::interfaces::GlobalScopeHelpers; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; +use storage_traits::StorageThreads; use timers::{TimerEventRequest, TimerId}; use uuid::Uuid; #[cfg(feature = "webgpu")] @@ -269,10 +270,15 @@ pub(crate) struct GlobalScope { in_error_reporting_mode: Cell, /// Associated resource threads for use by DOM objects like XMLHttpRequest, - /// including resource_thread, filemanager_thread and storage_thread + /// including resource_thread and filemanager_thread #[no_trace] resource_threads: ResourceThreads, + /// Associated resource threads for use by DOM objects like XMLHttpRequest, + /// including indexeddb_thread and storage_thread + #[no_trace] + storage_threads: StorageThreads, + /// The mechanism by which time-outs and intervals are scheduled. /// timers: OnceCell, @@ -754,6 +760,7 @@ impl GlobalScope { script_to_constellation_chan: ScriptToConstellationChan, script_to_embedder_chan: ScriptToEmbedderChan, resource_threads: ResourceThreads, + storage_threads: StorageThreads, origin: MutableOrigin, creation_url: ServoUrl, top_level_creation_url: Option, @@ -785,6 +792,7 @@ impl GlobalScope { script_to_embedder_chan, in_error_reporting_mode: Default::default(), resource_threads, + storage_threads, timers: OnceCell::default(), origin, creation_url, @@ -2761,6 +2769,11 @@ impl GlobalScope { self.resource_threads().sender() } + /// Get a reference to the [`StorageThreads`] for this [`GlobalScope`]. + pub(crate) fn storage_threads(&self) -> &StorageThreads { + &self.storage_threads + } + /// A sender to the event loop of this global scope. This either sends to the Worker event loop /// or the ScriptThread event loop in the case of a `Window`. This can be `None` for dedicated /// workers that are not currently handling a message. diff --git a/components/script/dom/idbcursor.rs b/components/script/dom/idbcursor.rs index 39a3cb2e963..574c4023a55 100644 --- a/components/script/dom/idbcursor.rs +++ b/components/script/dom/idbcursor.rs @@ -8,7 +8,7 @@ use dom_struct::dom_struct; use js::jsapi::Heap; use js::jsval::{JSVal, UndefinedValue}; use js::rust::MutableHandleValue; -use net_traits::indexeddb_thread::{IndexedDBKeyRange, IndexedDBKeyType, IndexedDBRecord}; +use storage_traits::indexeddb_thread::{IndexedDBKeyRange, IndexedDBKeyType, IndexedDBRecord}; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::IDBCursorBinding::{ diff --git a/components/script/dom/idbcursorwithvalue.rs b/components/script/dom/idbcursorwithvalue.rs index ab89f8391fb..16e657c2ca2 100644 --- a/components/script/dom/idbcursorwithvalue.rs +++ b/components/script/dom/idbcursorwithvalue.rs @@ -4,7 +4,7 @@ use dom_struct::dom_struct; use js::rust::MutableHandleValue; -use net_traits::indexeddb_thread::IndexedDBKeyRange; +use storage_traits::indexeddb_thread::IndexedDBKeyRange; use crate::dom::bindings::codegen::Bindings::IDBCursorBinding::IDBCursorDirection; use crate::dom::bindings::codegen::Bindings::IDBCursorWithValueBinding::IDBCursorWithValueMethods; diff --git a/components/script/dom/idbdatabase.rs b/components/script/dom/idbdatabase.rs index e16018c19e7..799b75446db 100644 --- a/components/script/dom/idbdatabase.rs +++ b/components/script/dom/idbdatabase.rs @@ -7,8 +7,8 @@ use std::cell::Cell; use base::IpcSend; use dom_struct::dom_struct; use ipc_channel::ipc::IpcSender; -use net_traits::indexeddb_thread::{IndexedDBThreadMsg, KeyPath, SyncOperation}; use profile_traits::ipc; +use storage_traits::indexeddb_thread::{IndexedDBThreadMsg, KeyPath, SyncOperation}; use stylo_atoms::Atom; use crate::dom::bindings::cell::DomRefCell; @@ -77,7 +77,7 @@ impl IDBDatabase { } fn get_idb_thread(&self) -> IpcSender { - self.global().resource_threads().sender() + self.global().storage_threads().sender() } pub fn get_name(&self) -> DOMString { diff --git a/components/script/dom/idbkeyrange.rs b/components/script/dom/idbkeyrange.rs index 7e823fa2a3b..10f574bd4e5 100644 --- a/components/script/dom/idbkeyrange.rs +++ b/components/script/dom/idbkeyrange.rs @@ -5,10 +5,10 @@ use dom_struct::dom_struct; use js::gc::MutableHandleValue; use js::rust::HandleValue; -use net_traits::indexeddb_thread::IndexedDBKeyRange; use script_bindings::codegen::GenericBindings::IDBKeyRangeBinding::IDBKeyRangeMethods; use script_bindings::root::DomRoot; use script_bindings::script_runtime::CanGc; +use storage_traits::indexeddb_thread::IndexedDBKeyRange; use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::import::module::SafeJSContext; diff --git a/components/script/dom/idbobjectstore.rs b/components/script/dom/idbobjectstore.rs index a9e1311393e..810286ea231 100644 --- a/components/script/dom/idbobjectstore.rs +++ b/components/script/dom/idbobjectstore.rs @@ -7,13 +7,13 @@ use dom_struct::dom_struct; use js::gc::MutableHandleValue; use js::jsval::NullValue; use js::rust::HandleValue; -use net_traits::indexeddb_thread::{ - AsyncOperation, AsyncReadOnlyOperation, AsyncReadWriteOperation, IndexedDBKeyType, - IndexedDBThreadMsg, SyncOperation, -}; use profile_traits::ipc; use script_bindings::conversions::SafeToJSValConvertible; use script_bindings::error::ErrorResult; +use storage_traits::indexeddb_thread::{ + AsyncOperation, AsyncReadOnlyOperation, AsyncReadWriteOperation, IndexedDBKeyType, + IndexedDBThreadMsg, SyncOperation, +}; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::IDBCursorBinding::IDBCursorDirection; @@ -131,7 +131,7 @@ impl IDBObjectStore { ); self.global() - .resource_threads() + .storage_threads() .send(IndexedDBThreadMsg::Sync(operation)) .unwrap(); diff --git a/components/script/dom/idbopendbrequest.rs b/components/script/dom/idbopendbrequest.rs index 81685fa1e94..5b9ad290433 100644 --- a/components/script/dom/idbopendbrequest.rs +++ b/components/script/dom/idbopendbrequest.rs @@ -7,9 +7,9 @@ use dom_struct::dom_struct; use ipc_channel::router::ROUTER; use js::jsval::UndefinedValue; use js::rust::HandleValue; -use net_traits::indexeddb_thread::{BackendResult, IndexedDBThreadMsg, SyncOperation}; use profile_traits::ipc; use script_bindings::conversions::SafeToJSValConvertible; +use storage_traits::indexeddb_thread::{BackendResult, IndexedDBThreadMsg, SyncOperation}; use stylo_atoms::Atom; use crate::dom::bindings::codegen::Bindings::IDBOpenDBRequestBinding::IDBOpenDBRequestMethods; @@ -287,7 +287,7 @@ impl IDBOpenDBRequest { ); if global - .resource_threads() + .storage_threads() .send(IndexedDBThreadMsg::Sync(open_operation)) .is_err() { @@ -322,7 +322,7 @@ impl IDBOpenDBRequest { ); if global - .resource_threads() + .storage_threads() .send(IndexedDBThreadMsg::Sync(delete_operation)) .is_err() { diff --git a/components/script/dom/idbrequest.rs b/components/script/dom/idbrequest.rs index aeb20f6f66a..dd0cea51761 100644 --- a/components/script/dom/idbrequest.rs +++ b/components/script/dom/idbrequest.rs @@ -11,13 +11,13 @@ use ipc_channel::router::ROUTER; use js::jsapi::Heap; use js::jsval::{DoubleValue, JSVal, ObjectValue, UndefinedValue}; use js::rust::HandleValue; -use net_traits::indexeddb_thread::{ - AsyncOperation, AsyncReadOnlyOperation, BackendError, BackendResult, IndexedDBKeyType, - IndexedDBRecord, IndexedDBThreadMsg, IndexedDBTxnMode, PutItemResult, -}; use profile_traits::ipc::IpcReceiver; use script_bindings::conversions::SafeToJSValConvertible; use serde::{Deserialize, Serialize}; +use storage_traits::indexeddb_thread::{ + AsyncOperation, AsyncReadOnlyOperation, BackendError, BackendResult, IndexedDBKeyType, + IndexedDBRecord, IndexedDBThreadMsg, IndexedDBTxnMode, PutItemResult, +}; use stylo_atoms::Atom; use crate::dom::bindings::codegen::Bindings::IDBRequestBinding::{ @@ -426,7 +426,7 @@ impl IDBRequest { transaction .global() - .resource_threads() + .storage_threads() .send(IndexedDBThreadMsg::Async( global.origin().immutable().clone(), transaction.get_db_name().to_string(), diff --git a/components/script/dom/idbtransaction.rs b/components/script/dom/idbtransaction.rs index 9ddbea75322..1b6716b0a46 100644 --- a/components/script/dom/idbtransaction.rs +++ b/components/script/dom/idbtransaction.rs @@ -8,9 +8,9 @@ use std::collections::HashMap; use base::IpcSend; use dom_struct::dom_struct; use ipc_channel::ipc::IpcSender; -use net_traits::indexeddb_thread::{IndexedDBThreadMsg, KeyPath, SyncOperation}; use profile_traits::ipc; use script_bindings::codegen::GenericUnionTypes::StringOrStringSequence; +use storage_traits::indexeddb_thread::{IndexedDBThreadMsg, KeyPath, SyncOperation}; use stylo_atoms::Atom; use crate::dom::bindings::cell::DomRefCell; @@ -106,7 +106,7 @@ impl IDBTransaction { let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap(); global - .resource_threads() + .storage_threads() .send(IndexedDBThreadMsg::Sync(SyncOperation::RegisterNewTxn( sender, global.origin().immutable().clone(), @@ -203,7 +203,7 @@ impl IDBTransaction { } fn get_idb_thread(&self) -> IpcSender { - self.global().resource_threads().sender() + self.global().storage_threads().sender() } fn object_store_parameters( @@ -211,7 +211,7 @@ impl IDBTransaction { object_store_name: &DOMString, ) -> Option { let global = self.global(); - let idb_sender = global.resource_threads().sender(); + let idb_sender = global.storage_threads().sender(); let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).expect("failed to create channel"); diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index 6a1cf7f98bd..789879206c2 100644 --- a/components/script/dom/storage.rs +++ b/components/script/dom/storage.rs @@ -5,9 +5,9 @@ use base::generic_channel::{GenericSend, SendResult}; use base::id::WebViewId; use constellation_traits::ScriptToConstellationMessage; use dom_struct::dom_struct; -use net_traits::storage_thread::{StorageThreadMsg, StorageType}; use profile_traits::generic_channel; use servo_url::ServoUrl; +use storage_traits::storage_thread::{StorageThreadMsg, StorageType}; use crate::dom::bindings::codegen::Bindings::StorageBinding::StorageMethods; use crate::dom::bindings::error::{Error, ErrorResult}; @@ -57,7 +57,7 @@ impl Storage { } fn send_storage_msg(&self, msg: StorageThreadMsg) -> SendResult { - GenericSend::send(self.global().resource_threads(), msg) + GenericSend::send(self.global().storage_threads(), msg) } } diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index bbfcc635aaa..f56254af720 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -67,7 +67,6 @@ use net_traits::image_cache::{ ImageCache, ImageCacheResponseMessage, ImageLoadListener, ImageResponse, PendingImageId, PendingImageResponse, RasterizationCompleteResponse, }; -use net_traits::storage_thread::StorageType; use num_traits::ToPrimitive; use profile_traits::generic_channel as ProfiledGenericChannel; use profile_traits::mem::ProfilerChan as MemProfilerChan; @@ -83,6 +82,8 @@ use servo_arc::Arc as ServoArc; use servo_config::{opts, pref}; use servo_geometry::{DeviceIndependentIntRect, f32_rect_to_au_rect}; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; +use storage_traits::StorageThreads; +use storage_traits::storage_thread::StorageType; use style::error_reporting::{ContextualParseError, ParseErrorReporter}; use style::properties::PropertyId; use style::properties::style_structs::Font; @@ -3210,6 +3211,7 @@ impl Window { image_cache_sender: IpcSender, image_cache: Arc, resource_threads: ResourceThreads, + storage_threads: StorageThreads, #[cfg(feature = "bluetooth")] bluetooth_thread: IpcSender, mem_profiler_chan: MemProfilerChan, time_profiler_chan: TimeProfilerChan, @@ -3257,6 +3259,7 @@ impl Window { constellation_chan, embedder_chan, resource_threads, + storage_threads, origin, creation_url, Some(top_level_creation_url), diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs index c02169929a8..1c30b439604 100644 --- a/components/script/dom/windowproxy.rs +++ b/components/script/dom/windowproxy.rs @@ -35,10 +35,10 @@ use js::rust::wrappers::{JS_TransplantObject, NewWindowProxy, SetWindowProxy}; use js::rust::{Handle, MutableHandle, MutableHandleValue, get_object_class}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use net_traits::request::Referrer; -use net_traits::storage_thread::StorageThreadMsg; use script_traits::NewLayoutInfo; use serde::{Deserialize, Serialize}; use servo_url::{ImmutableOrigin, ServoUrl}; +use storage_traits::storage_thread::StorageThreadMsg; use style::attr::parse_integer; use crate::dom::bindings::cell::DomRefCell; @@ -359,7 +359,7 @@ impl WindowProxy { dest: response.new_webview_id, }; - GenericSend::send(document.global().resource_threads(), msg).unwrap(); + GenericSend::send(document.global().storage_threads(), msg).unwrap(); receiver.recv().unwrap(); } Some(new_window_proxy) diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index 569755f83c8..43ca9f86aec 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -86,6 +86,7 @@ pub(crate) fn prepare_workerscope_init( ) -> WorkerGlobalScopeInit { WorkerGlobalScopeInit { resource_threads: global.resource_threads().clone(), + storage_threads: global.storage_threads().clone(), mem_profiler_chan: global.mem_profiler_chan().clone(), to_devtools_sender: global.devtools_chan().cloned(), time_profiler_chan: global.time_profiler_chan().clone(), @@ -189,6 +190,7 @@ impl WorkerGlobalScope { init.script_to_constellation_chan, init.script_to_embedder_chan, init.resource_threads, + init.storage_threads, MutableOrigin::new(init.origin), init.creation_url, None, diff --git a/components/script/dom/workletglobalscope.rs b/components/script/dom/workletglobalscope.rs index b719a46767a..cff85db1681 100644 --- a/components/script/dom/workletglobalscope.rs +++ b/components/script/dom/workletglobalscope.rs @@ -19,6 +19,7 @@ use profile_traits::{mem, time}; use script_bindings::realms::InRealm; use script_traits::Painter; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; +use storage_traits::StorageThreads; use stylo_atoms::Atom; use crate::dom::bindings::inheritance::Castable; @@ -102,6 +103,7 @@ impl WorkletGlobalScope { script_to_constellation_chan, init.to_embedder_sender.clone(), init.resource_threads.clone(), + init.storage_threads.clone(), MutableOrigin::new(ImmutableOrigin::new_opaque()), base_url.clone(), None, @@ -191,6 +193,8 @@ pub(crate) struct WorkletGlobalScopeInit { pub(crate) to_script_thread_sender: Sender, /// Channel to a resource thread pub(crate) resource_threads: ResourceThreads, + /// Channels to the [`StorageThreads`]. + pub(crate) storage_threads: StorageThreads, /// Channel to the memory profiler pub(crate) mem_profiler_chan: mem::ProfilerChan, /// Channel to the time profiler diff --git a/components/script/indexed_db.rs b/components/script/indexed_db.rs index 5eacddbb774..86f379bbdd8 100644 --- a/components/script/indexed_db.rs +++ b/components/script/indexed_db.rs @@ -18,10 +18,10 @@ use js::jsapi::{ use js::jsval::{DoubleValue, UndefinedValue}; use js::rust::wrappers::{IsArrayObject, JS_GetProperty, JS_HasOwnProperty, JS_IsIdentifier}; use js::rust::{HandleValue, IntoHandle, IntoMutableHandle, MutableHandleValue}; -use net_traits::indexeddb_thread::{BackendResult, IndexedDBKeyRange, IndexedDBKeyType}; use profile_traits::ipc; use profile_traits::ipc::IpcReceiver; use serde::{Deserialize, Serialize}; +use storage_traits::indexeddb_thread::{BackendResult, IndexedDBKeyRange, IndexedDBKeyType}; use crate::dom::bindings::codegen::Bindings::BlobBinding::BlobMethods; use crate::dom::bindings::codegen::Bindings::FileBinding::FileMethods; diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index e4cb73c3d09..3773ab56968 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -73,7 +73,6 @@ use metrics::MAX_TASK_NS; use net_traits::image_cache::{ImageCache, ImageCacheResponseMessage}; use net_traits::request::{Referrer, RequestId}; use net_traits::response::ResponseInit; -use net_traits::storage_thread::StorageType; use net_traits::{ FetchMetadata, FetchResponseListener, FetchResponseMsg, Metadata, NetworkError, ResourceFetchTiming, ResourceThreads, ResourceTimingType, @@ -89,6 +88,8 @@ use script_traits::{ }; use servo_config::{opts, prefs}; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; +use storage_traits::StorageThreads; +use storage_traits::storage_thread::StorageType; use style::thread_state::{self, ThreadState}; use stylo_atoms::Atom; use timers::{TimerEventRequest, TimerId, TimerScheduler}; @@ -250,6 +251,9 @@ pub struct ScriptThread { #[no_trace] resource_threads: ResourceThreads, + #[no_trace] + storage_threads: StorageThreads, + /// A queue of tasks to be executed in this script-thread. task_queue: TaskQueue, @@ -751,6 +755,7 @@ impl ScriptThread { let init = WorkletGlobalScopeInit { to_script_thread_sender: script_thread.senders.self_sender.clone(), resource_threads: script_thread.resource_threads.clone(), + storage_threads: script_thread.storage_threads.clone(), mem_profiler_chan: script_thread.senders.memory_profiler_sender.clone(), time_profiler_chan: script_thread.senders.time_profiler_sender.clone(), devtools_chan: script_thread.senders.devtools_server_sender.clone(), @@ -950,6 +955,7 @@ impl ScriptThread { script_to_constellation_chan, senders.pipeline_to_embedder_sender.clone(), state.resource_threads.clone(), + state.storage_threads.clone(), #[cfg(feature = "webgpu")] gpu_id_hub.clone(), CanGc::note(), @@ -966,6 +972,7 @@ impl ScriptThread { receivers, image_cache: state.image_cache.clone(), resource_threads: state.resource_threads, + storage_threads: state.storage_threads, task_queue, background_hang_monitor, closing, @@ -3291,6 +3298,7 @@ impl ScriptThread { self.senders.image_cache_sender.clone(), image_cache.clone(), self.resource_threads.clone(), + self.storage_threads.clone(), #[cfg(feature = "bluetooth")] self.senders.bluetooth_sender.clone(), self.senders.memory_profiler_sender.clone(), diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index b967a9bbf71..66ddc00e6df 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -110,6 +110,8 @@ servo_allocator = { path = "../allocator" } servo_config = { path = "../config" } servo_geometry = { path = "../geometry" } servo_url = { path = "../url" } +storage = { path = "../storage" } +storage_traits = { workspace = true } stylo = { workspace = true } stylo_traits = { workspace = true } surfman = { workspace = true } diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 9bbe6f53ec7..2c8f19deed0 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -108,6 +108,7 @@ use servo_geometry::{ use servo_media::ServoMedia; use servo_media::player::context::GlContext; use servo_url::ServoUrl; +use storage::new_storage_threads; use style::global_style_data::StyleThreadPool; use webgl::WebGLComm; #[cfg(feature = "webgpu")] @@ -1163,12 +1164,15 @@ fn create_constellation( time_profiler_chan.clone(), mem_profiler_chan.clone(), embedder_proxy.clone(), - config_dir, + config_dir.clone(), opts.certificate_path.clone(), opts.ignore_certificate_errors, Arc::new(protocols), ); + let (private_storage_threads, public_storage_threads) = + new_storage_threads(mem_profiler_chan.clone(), config_dir); + let system_font_service = Arc::new( SystemFontService::spawn( compositor_proxy.cross_process_compositor_api.clone(), @@ -1186,6 +1190,8 @@ fn create_constellation( system_font_service, public_resource_threads, private_resource_threads, + public_storage_threads, + private_storage_threads, time_profiler_chan, mem_profiler_chan, webrender_document, diff --git a/components/shared/constellation/Cargo.toml b/components/shared/constellation/Cargo.toml index e381bc91bc8..13057f82b6a 100644 --- a/components/shared/constellation/Cargo.toml +++ b/components/shared/constellation/Cargo.toml @@ -37,6 +37,7 @@ rustc-hash = { workspace = true } serde = { workspace = true } servo_config = { path = "../../config" } servo_url = { path = "../../url" } +storage_traits = { workspace = true } strum = { workspace = true } strum_macros = { workspace = true } stylo_traits = { workspace = true } diff --git a/components/shared/constellation/from_script_message.rs b/components/shared/constellation/from_script_message.rs index 7264ae53327..9480ee578a7 100644 --- a/components/shared/constellation/from_script_message.rs +++ b/components/shared/constellation/from_script_message.rs @@ -27,13 +27,14 @@ use ipc_channel::ipc::IpcSender; use malloc_size_of_derive::MallocSizeOf; use net_traits::policy_container::PolicyContainer; use net_traits::request::{Destination, InsecureRequestsPolicy, Referrer, RequestBody}; -use net_traits::storage_thread::StorageType; use net_traits::{ReferrerPolicy, ResourceThreads}; use profile_traits::mem::MemoryReportResult; use profile_traits::{mem, time as profile_time}; use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use servo_url::{ImmutableOrigin, ServoUrl}; +use storage_traits::StorageThreads; +use storage_traits::storage_thread::StorageType; use strum_macros::IntoStaticStr; #[cfg(feature = "webgpu")] use webgpu_traits::{WebGPU, WebGPUAdapterResponse}; @@ -434,6 +435,8 @@ pub struct IFrameLoadInfoWithData { pub struct WorkerGlobalScopeInit { /// Chan to a resource thread pub resource_threads: ResourceThreads, + /// Chan to a storage thread + pub storage_threads: StorageThreads, /// Chan to the memory profiler pub mem_profiler_chan: mem::ProfilerChan, /// Chan to the time profiler diff --git a/components/shared/net/lib.rs b/components/shared/net/lib.rs index d33bf9ffcf9..f62dd0ab4ce 100644 --- a/components/shared/net/lib.rs +++ b/components/shared/net/lib.rs @@ -9,7 +9,6 @@ use std::sync::{LazyLock, OnceLock}; use std::thread::{self, JoinHandle}; use base::cross_process_instant::CrossProcessInstant; -use base::generic_channel::{GenericSend, GenericSender, SendResult}; use base::id::{CookieStoreId, HistoryStateId}; use base::{IpcSend, IpcSendResult}; use content_security_policy::{self as csp}; @@ -33,23 +32,19 @@ use servo_url::{ImmutableOrigin, ServoUrl}; use crate::filemanager_thread::FileManagerThreadMsg; use crate::http_status::HttpStatus; -use crate::indexeddb_thread::IndexedDBThreadMsg; use crate::request::{Request, RequestBuilder}; use crate::response::{HttpsState, Response, ResponseInit}; -use crate::storage_thread::StorageThreadMsg; pub mod blob_url_store; pub mod filemanager_thread; pub mod http_status; pub mod image_cache; -pub mod indexeddb_thread; pub mod mime_classifier; pub mod policy_container; pub mod pub_domains; pub mod quality; pub mod request; pub mod response; -pub mod storage_thread; /// pub const DOCUMENT_ACCEPT_HEADER_VALUE: HeaderValue = @@ -423,21 +418,11 @@ pub type CoreResourceThread = IpcSender; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ResourceThreads { pub core_thread: CoreResourceThread, - storage_thread: GenericSender, - idb_thread: IpcSender, } impl ResourceThreads { - pub fn new( - c: CoreResourceThread, - s: GenericSender, - i: IpcSender, - ) -> ResourceThreads { - ResourceThreads { - core_thread: c, - storage_thread: s, - idb_thread: i, - } + pub fn new(core_thread: CoreResourceThread) -> ResourceThreads { + ResourceThreads { core_thread } } pub fn clear_cache(&self) { @@ -455,26 +440,6 @@ impl IpcSend for ResourceThreads { } } -impl IpcSend for ResourceThreads { - fn send(&self, msg: IndexedDBThreadMsg) -> IpcSendResult { - self.idb_thread.send(msg).map_err(IpcError::Bincode) - } - - fn sender(&self) -> IpcSender { - self.idb_thread.clone() - } -} - -impl GenericSend for ResourceThreads { - fn send(&self, msg: StorageThreadMsg) -> SendResult { - self.storage_thread.send(msg) - } - - fn sender(&self) -> GenericSender { - self.storage_thread.clone() - } -} - // Ignore the sub-fields malloc_size_of_is_0!(ResourceThreads); diff --git a/components/shared/script/Cargo.toml b/components/shared/script/Cargo.toml index 0e5f6db2fb6..6563ea94a94 100644 --- a/components/shared/script/Cargo.toml +++ b/components/shared/script/Cargo.toml @@ -39,6 +39,7 @@ rustc-hash = { workspace = true } serde = { workspace = true } servo_config = { path = "../../config" } servo_url = { path = "../../url" } +storage_traits = { workspace = true } strum = { workspace = true, features = ["derive"] } strum_macros = { workspace = true } stylo_atoms = { workspace = true } diff --git a/components/shared/script/lib.rs b/components/shared/script/lib.rs index f419d93934b..d84c129cb57 100644 --- a/components/shared/script/lib.rs +++ b/components/shared/script/lib.rs @@ -38,13 +38,14 @@ use malloc_size_of_derive::MallocSizeOf; use media::WindowGLContext; use net_traits::ResourceThreads; use net_traits::image_cache::ImageCache; -use net_traits::storage_thread::StorageType; use pixels::PixelFormat; use profile_traits::mem; use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use servo_config::prefs::PrefValue; use servo_url::{ImmutableOrigin, ServoUrl}; +use storage_traits::StorageThreads; +use storage_traits::storage_thread::StorageType; use strum_macros::IntoStaticStr; use style_traits::{CSSPixel, SpeculativePainter}; use stylo_atoms::Atom; @@ -330,6 +331,8 @@ pub struct InitialScriptState { pub background_hang_monitor_register: Box, /// A channel to the resource manager thread. pub resource_threads: ResourceThreads, + /// A channel to the storage manager thread. + pub storage_threads: StorageThreads, /// A channel to the bluetooth thread. #[cfg(feature = "bluetooth")] pub bluetooth_sender: IpcSender, diff --git a/components/shared/storage/Cargo.toml b/components/shared/storage/Cargo.toml new file mode 100644 index 00000000000..2715aed93e2 --- /dev/null +++ b/components/shared/storage/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "storage_traits" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +publish.workspace = true +rust-version.workspace = true + +[lib] +name = "storage_traits" +path = "lib.rs" + +[dependencies] +base = { workspace = true } +ipc-channel = { workspace = true } +malloc_size_of = { workspace = true } +malloc_size_of_derive = { workspace = true } +profile_traits = { path = "../profile" } +serde = { workspace = true } +servo_url = { path = "../../url" } diff --git a/components/shared/net/indexeddb_thread.rs b/components/shared/storage/indexeddb_thread.rs similarity index 100% rename from components/shared/net/indexeddb_thread.rs rename to components/shared/storage/indexeddb_thread.rs diff --git a/components/shared/storage/lib.rs b/components/shared/storage/lib.rs new file mode 100644 index 00000000000..47c2b9ad3cd --- /dev/null +++ b/components/shared/storage/lib.rs @@ -0,0 +1,56 @@ +/* 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 base::generic_channel::{GenericSend, GenericSender, SendResult}; +use base::{IpcSend, IpcSendResult}; +use ipc_channel::ipc::{IpcError, IpcSender}; +use malloc_size_of::malloc_size_of_is_0; +use serde::{Deserialize, Serialize}; + +use crate::indexeddb_thread::IndexedDBThreadMsg; +use crate::storage_thread::StorageThreadMsg; + +pub mod indexeddb_thread; +pub mod storage_thread; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct StorageThreads { + storage_thread: GenericSender, + idb_thread: IpcSender, +} + +impl StorageThreads { + pub fn new( + storage_thread: GenericSender, + idb_thread: IpcSender, + ) -> StorageThreads { + StorageThreads { + storage_thread, + idb_thread, + } + } +} + +impl IpcSend for StorageThreads { + fn send(&self, msg: IndexedDBThreadMsg) -> IpcSendResult { + self.idb_thread.send(msg).map_err(IpcError::Bincode) + } + + fn sender(&self) -> IpcSender { + self.idb_thread.clone() + } +} + +impl GenericSend for StorageThreads { + fn send(&self, msg: StorageThreadMsg) -> SendResult { + self.storage_thread.send(msg) + } + + fn sender(&self) -> GenericSender { + self.storage_thread.clone() + } +} + +// Ignore the sub-fields +malloc_size_of_is_0!(StorageThreads); diff --git a/components/shared/net/storage_thread.rs b/components/shared/storage/storage_thread.rs similarity index 100% rename from components/shared/net/storage_thread.rs rename to components/shared/storage/storage_thread.rs diff --git a/components/storage/Cargo.toml b/components/storage/Cargo.toml new file mode 100644 index 00000000000..7ce02be4ac5 --- /dev/null +++ b/components/storage/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "storage" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +publish.workspace = true +rust-version.workspace = true +autotests = false # Inhibit lookup for tests/*.rs without [[test]] sections + +[lib] +name = "storage" +path = "lib.rs" + +[dependencies] +base = { workspace = true } +bincode = { workspace = true } +ipc-channel = { workspace = true } +malloc_size_of = { workspace = true } +malloc_size_of_derive = { workspace = true } +log = { workspace = true } +profile_traits = { workspace = true } +rusqlite = { version = "0.37", features = ["bundled"] } +rustc-hash = { workspace = true } +sea-query = { version = "1.0.0-rc.9", default-features = false, features = ["backend-sqlite", "derive"] } +sea-query-rusqlite = { version = "0.8.0-rc.8" } +serde = { workspace = true } +serde_json = { workspace = true } +servo_config = { path = "../config" } +servo_url = { path = "../url" } +storage_traits = { workspace = true } +tempfile = "3" +tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync"] } +tokio-rustls = { workspace = true } +tokio-stream = "0.1" +tokio-util = { version = "0.7.12", default-features = false, features = ["codec", "io"] } +uuid = { workspace = true } + +[[test]] +name = "main" +path = "tests/main.rs" diff --git a/components/net/indexeddb/engines/mod.rs b/components/storage/indexeddb/engines/mod.rs similarity index 94% rename from components/net/indexeddb/engines/mod.rs rename to components/storage/indexeddb/engines/mod.rs index 2ee4f732d5a..158ef6ac17b 100644 --- a/components/net/indexeddb/engines/mod.rs +++ b/components/storage/indexeddb/engines/mod.rs @@ -4,7 +4,9 @@ use std::collections::VecDeque; -use net_traits::indexeddb_thread::{AsyncOperation, CreateObjectResult, IndexedDBTxnMode, KeyPath}; +use storage_traits::indexeddb_thread::{ + AsyncOperation, CreateObjectResult, IndexedDBTxnMode, KeyPath, +}; use tokio::sync::oneshot; pub use self::sqlite::SqliteEngine; diff --git a/components/net/indexeddb/engines/sqlite.rs b/components/storage/indexeddb/engines/sqlite.rs similarity index 99% rename from components/net/indexeddb/engines/sqlite.rs rename to components/storage/indexeddb/engines/sqlite.rs index 02d510e7b13..fcbec68fa86 100644 --- a/components/net/indexeddb/engines/sqlite.rs +++ b/components/storage/indexeddb/engines/sqlite.rs @@ -4,22 +4,22 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; +use base::threadpool::ThreadPool; use ipc_channel::ipc::IpcSender; use log::{error, info}; -use net_traits::indexeddb_thread::{ - AsyncOperation, AsyncReadOnlyOperation, AsyncReadWriteOperation, BackendError, BackendResult, - CreateObjectResult, IndexedDBKeyRange, IndexedDBKeyType, IndexedDBRecord, IndexedDBTxnMode, - KeyPath, PutItemResult, -}; use rusqlite::{Connection, Error, OptionalExtension, params}; use sea_query::{Condition, Expr, ExprTrait, IntoCondition, SqliteQueryBuilder}; use sea_query_rusqlite::RusqliteBinder; use serde::Serialize; +use storage_traits::indexeddb_thread::{ + AsyncOperation, AsyncReadOnlyOperation, AsyncReadWriteOperation, BackendError, BackendResult, + CreateObjectResult, IndexedDBKeyRange, IndexedDBKeyType, IndexedDBRecord, IndexedDBTxnMode, + KeyPath, PutItemResult, +}; use tokio::sync::oneshot; use crate::indexeddb::engines::{KvsEngine, KvsTransaction}; use crate::indexeddb::idb_thread::IndexedDBDescription; -use crate::resource_thread::CoreResourceThreadPool; mod create; mod database_model; @@ -75,8 +75,8 @@ fn range_to_query(range: IndexedDBKeyRange) -> Condition { pub struct SqliteEngine { db_path: PathBuf, connection: Connection, - read_pool: Arc, - write_pool: Arc, + read_pool: Arc, + write_pool: Arc, } impl SqliteEngine { @@ -84,7 +84,7 @@ impl SqliteEngine { pub fn new( base_dir: &Path, db_info: &IndexedDBDescription, - pool: Arc, + pool: Arc, ) -> Result { let mut db_path = PathBuf::new(); db_path.push(base_dir); diff --git a/components/net/indexeddb/engines/sqlite/create.rs b/components/storage/indexeddb/engines/sqlite/create.rs similarity index 100% rename from components/net/indexeddb/engines/sqlite/create.rs rename to components/storage/indexeddb/engines/sqlite/create.rs diff --git a/components/net/indexeddb/engines/sqlite/database_model.rs b/components/storage/indexeddb/engines/sqlite/database_model.rs similarity index 100% rename from components/net/indexeddb/engines/sqlite/database_model.rs rename to components/storage/indexeddb/engines/sqlite/database_model.rs diff --git a/components/net/indexeddb/engines/sqlite/object_data_model.rs b/components/storage/indexeddb/engines/sqlite/object_data_model.rs similarity index 100% rename from components/net/indexeddb/engines/sqlite/object_data_model.rs rename to components/storage/indexeddb/engines/sqlite/object_data_model.rs diff --git a/components/net/indexeddb/engines/sqlite/object_store_index_model.rs b/components/storage/indexeddb/engines/sqlite/object_store_index_model.rs similarity index 100% rename from components/net/indexeddb/engines/sqlite/object_store_index_model.rs rename to components/storage/indexeddb/engines/sqlite/object_store_index_model.rs diff --git a/components/net/indexeddb/engines/sqlite/object_store_model.rs b/components/storage/indexeddb/engines/sqlite/object_store_model.rs similarity index 100% rename from components/net/indexeddb/engines/sqlite/object_store_model.rs rename to components/storage/indexeddb/engines/sqlite/object_store_model.rs diff --git a/components/net/indexeddb/idb_thread.rs b/components/storage/indexeddb/idb_thread.rs similarity index 98% rename from components/net/indexeddb/idb_thread.rs rename to components/storage/indexeddb/idb_thread.rs index 4dae0041039..507351d1735 100644 --- a/components/net/indexeddb/idb_thread.rs +++ b/components/storage/indexeddb/idb_thread.rs @@ -8,19 +8,19 @@ use std::path::PathBuf; use std::sync::Arc; use std::thread; +use base::threadpool::ThreadPool; use ipc_channel::ipc::{self, IpcError, IpcReceiver, IpcSender}; use log::{debug, warn}; -use net_traits::indexeddb_thread::{ - AsyncOperation, BackendError, BackendResult, CreateObjectResult, DbResult, IndexedDBThreadMsg, - IndexedDBTxnMode, KeyPath, SyncOperation, -}; use rustc_hash::FxHashMap; use servo_config::pref; use servo_url::origin::ImmutableOrigin; +use storage_traits::indexeddb_thread::{ + AsyncOperation, BackendError, BackendResult, CreateObjectResult, DbResult, IndexedDBThreadMsg, + IndexedDBTxnMode, KeyPath, SyncOperation, +}; use uuid::Uuid; use crate::indexeddb::engines::{KvsEngine, KvsOperation, KvsTransaction, SqliteEngine}; -use crate::resource_thread::CoreResourceThreadPool; pub trait IndexedDBThreadFactory { fn new(config_dir: Option) -> Self; @@ -196,7 +196,7 @@ struct IndexedDBManager { port: IpcReceiver, idb_base_dir: PathBuf, databases: HashMap>, - thread_pool: Arc, + thread_pool: Arc, } impl IndexedDBManager { @@ -215,10 +215,7 @@ impl IndexedDBManager { port, idb_base_dir, databases: HashMap::new(), - thread_pool: Arc::new(CoreResourceThreadPool::new( - thread_count, - "IndexedDB".to_string(), - )), + thread_pool: Arc::new(ThreadPool::new(thread_count, "IndexedDB".to_string())), } } } diff --git a/components/net/indexeddb/mod.rs b/components/storage/indexeddb/mod.rs similarity index 100% rename from components/net/indexeddb/mod.rs rename to components/storage/indexeddb/mod.rs diff --git a/components/storage/lib.rs b/components/storage/lib.rs new file mode 100644 index 00000000000..16106b4898f --- /dev/null +++ b/components/storage/lib.rs @@ -0,0 +1,9 @@ +/* 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/. */ + +pub mod indexeddb; +mod storage_thread; +mod webstorage_thread; + +pub use storage_thread::new_storage_threads; diff --git a/components/storage/storage_thread.rs b/components/storage/storage_thread.rs new file mode 100644 index 00000000000..ede53cf3bc3 --- /dev/null +++ b/components/storage/storage_thread.rs @@ -0,0 +1,29 @@ +/* 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 base::generic_channel::GenericSender; +use ipc_channel::ipc::IpcSender; +use profile_traits::mem::ProfilerChan as MemProfilerChan; +use storage_traits::StorageThreads; +use storage_traits::indexeddb_thread::IndexedDBThreadMsg; +use storage_traits::storage_thread::StorageThreadMsg; + +use crate::indexeddb::IndexedDBThreadFactory; +use crate::webstorage_thread::StorageThreadFactory; + +#[allow(clippy::too_many_arguments)] +pub fn new_storage_threads( + mem_profiler_chan: MemProfilerChan, + config_dir: Option, +) -> (StorageThreads, StorageThreads) { + let idb: IpcSender = IndexedDBThreadFactory::new(config_dir.clone()); + let storage: GenericSender = + StorageThreadFactory::new(config_dir, mem_profiler_chan); + ( + StorageThreads::new(storage.clone(), idb.clone()), + StorageThreads::new(storage, idb), + ) +} diff --git a/components/storage/tests/main.rs b/components/storage/tests/main.rs new file mode 100644 index 00000000000..13faf367c2a --- /dev/null +++ b/components/storage/tests/main.rs @@ -0,0 +1,5 @@ +/* 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/. */ + +mod sqlite; diff --git a/components/net/tests/sqlite.rs b/components/storage/tests/sqlite.rs similarity index 97% rename from components/net/tests/sqlite.rs rename to components/storage/tests/sqlite.rs index 29be2c4255e..23406ed020a 100644 --- a/components/net/tests/sqlite.rs +++ b/components/storage/tests/sqlite.rs @@ -4,15 +4,15 @@ use std::collections::VecDeque; use std::sync::Arc; -use net::indexeddb::engines::{KvsEngine, KvsOperation, KvsTransaction, SqliteEngine}; -use net::indexeddb::idb_thread::IndexedDBDescription; -use net::resource_thread::CoreResourceThreadPool; -use net_traits::indexeddb_thread::{ +use base::threadpool::ThreadPool; +use serde::{Deserialize, Serialize}; +use servo_url::ImmutableOrigin; +use storage::indexeddb::engines::{KvsEngine, KvsOperation, KvsTransaction, SqliteEngine}; +use storage::indexeddb::idb_thread::IndexedDBDescription; +use storage_traits::indexeddb_thread::{ AsyncOperation, AsyncReadOnlyOperation, AsyncReadWriteOperation, CreateObjectResult, IndexedDBKeyRange, IndexedDBKeyType, IndexedDBTxnMode, KeyPath, PutItemResult, }; -use serde::{Deserialize, Serialize}; -use servo_url::ImmutableOrigin; use url::Host; fn test_origin() -> ImmutableOrigin { @@ -23,8 +23,8 @@ fn test_origin() -> ImmutableOrigin { ) } -fn get_pool() -> Arc { - Arc::new(CoreResourceThreadPool::new(1, "test".to_string())) +fn get_pool() -> Arc { + Arc::new(ThreadPool::new(1, "test".to_string())) } #[test] diff --git a/components/net/storage_thread.rs b/components/storage/webstorage_thread.rs similarity index 99% rename from components/net/storage_thread.rs rename to components/storage/webstorage_thread.rs index f1485afb549..3888fe37cba 100644 --- a/components/net/storage_thread.rs +++ b/components/storage/webstorage_thread.rs @@ -10,13 +10,13 @@ use std::thread; use base::generic_channel::{self, GenericReceiver, GenericSender}; use base::id::WebViewId; use malloc_size_of::MallocSizeOf; -use net_traits::storage_thread::{StorageThreadMsg, StorageType}; use profile_traits::mem::{ ProcessReports, ProfilerChan as MemProfilerChan, Report, ReportKind, perform_memory_report, }; use profile_traits::path; use rustc_hash::FxHashMap; use servo_url::ServoUrl; +use storage_traits::storage_thread::{StorageThreadMsg, StorageType}; const QUOTA_SIZE_LIMIT: usize = 5 * 1024 * 1024;