Initial IndexedDB Support (#33044)

Adds indexeddb support to servo. At the moment heed is being used as the
backend, although this can be swapped out by implementing `KvsEngine`.
This PR adds a thread + a thread pool for Indexeddb related operations.
Also `database_access_task_source` is added for Indexeddb related
operations.

This is a partial rewrite of #25214. (Reopened due to branching issue)

Fixes #6963

---------

Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
Co-authored-by: Rasmus Viitanen <rasviitanen@gmail.com>
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Ashwin Naren 2025-06-18 22:19:07 -07:00 committed by GitHub
parent d33cf8fbd1
commit ed9a79f3f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
259 changed files with 11141 additions and 8 deletions

View file

@ -0,0 +1,173 @@
/* 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 ipc_channel::ipc::IpcSender;
use serde::{Deserialize, Serialize};
use servo_url::origin::ImmutableOrigin;
#[derive(Debug, Deserialize, Serialize)]
pub enum IndexedDBThreadReturnType {
Open(Option<u64>),
NextSerialNumber(u64),
StartTransaction(Result<(), ()>),
Commit(Result<(), ()>),
Version(u64),
CreateObjectStore(Option<String>),
UpgradeVersion(Result<u64, ()>),
KVResult(Option<Vec<u8>>),
Exit,
}
// https://www.w3.org/TR/IndexedDB-2/#enumdef-idbtransactionmode
#[derive(Debug, Deserialize, Serialize)]
pub enum IndexedDBTxnMode {
Readonly,
Readwrite,
Versionchange,
}
// https://www.w3.org/TR/IndexedDB-2/#key-type
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum IndexedDBKeyType {
Number(Vec<u8>),
String(Vec<u8>),
Binary(Vec<u8>),
Date(Vec<u8>),
// FIXME:(arihant2math) implment Array(),
}
// https://www.w3.org/TR/IndexedDB-2/#key-range
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(unused)]
pub enum IndexedDBKeyRange {}
// Operations that are not executed instantly, but rather added to a
// queue that is eventually run.
#[derive(Debug, Deserialize, Serialize)]
pub enum AsyncOperation {
/// Gets the value associated with the given key in the associated idb data
GetItem(
IndexedDBKeyType, // Key
),
/// Sets the value of the given key in the associated idb data
PutItem(
IndexedDBKeyType, // Key
Vec<u8>, // Value
bool, // Should overwrite
),
/// Removes the key/value pair for the given key in the associated idb data
RemoveItem(
IndexedDBKeyType, // Key
),
Count(
IndexedDBKeyType, // Key
),
}
#[derive(Debug, Deserialize, Serialize)]
pub enum SyncOperation {
// Upgrades the version of the database
UpgradeVersion(
IpcSender<IndexedDBThreadReturnType>,
ImmutableOrigin,
String, // Database
u64, // Serial number for the transaction
u64, // Version to upgrade to
),
// Checks if an object store has a key generator, used in e.g. Put
HasKeyGenerator(
IpcSender<bool>,
ImmutableOrigin,
String, // Database
String, // Store
),
// Commits changes of a transaction to the database
Commit(
IpcSender<IndexedDBThreadReturnType>,
ImmutableOrigin,
String, // Database
u64, // Transaction serial number
),
// Creates a new store for the database
CreateObjectStore(
IpcSender<Result<(), ()>>,
ImmutableOrigin,
String, // Database
String, // Store
bool,
),
DeleteObjectStore(
IpcSender<Result<(), ()>>,
ImmutableOrigin,
String, // Database
String, // Store
),
CloseDatabase(
IpcSender<Result<(), ()>>,
ImmutableOrigin,
String, // Database
),
OpenDatabase(
IpcSender<u64>, // Returns the version
ImmutableOrigin,
String, // Database
Option<u64>, // Eventual version
),
// Deletes the database
DeleteDatabase(
IpcSender<Result<(), ()>>,
ImmutableOrigin,
String, // Database
),
// Returns an unique identifier that is used to be able to
// commit/abort transactions.
RegisterNewTxn(
IpcSender<u64>,
ImmutableOrigin,
String, // Database
),
// Starts executing the requests of a transaction
// https://www.w3.org/TR/IndexedDB-2/#transaction-start
StartTransaction(
IpcSender<Result<(), ()>>,
ImmutableOrigin,
String, // Database
u64, // The serial number of the mutating transaction
),
// Returns the version of the database
Version(
IpcSender<u64>,
ImmutableOrigin,
String, // Database
),
/// Send a reply when done cleaning up thread resources and then shut it down
Exit(IpcSender<IndexedDBThreadReturnType>),
}
#[derive(Debug, Deserialize, Serialize)]
pub enum IndexedDBThreadMsg {
Sync(SyncOperation),
Async(
IpcSender<Option<Vec<u8>>>, // Sender to send the result of the async operation
ImmutableOrigin,
String, // Database
String, // ObjectStore
u64, // Serial number of the transaction that requests this operation
IndexedDBTxnMode,
AsyncOperation,
),
}

View file

@ -32,6 +32,7 @@ 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;
@ -40,6 +41,7 @@ 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;
@ -414,13 +416,19 @@ where
pub struct ResourceThreads {
pub core_thread: CoreResourceThread,
storage_thread: IpcSender<StorageThreadMsg>,
idb_thread: IpcSender<IndexedDBThreadMsg>,
}
impl ResourceThreads {
pub fn new(c: CoreResourceThread, s: IpcSender<StorageThreadMsg>) -> ResourceThreads {
pub fn new(
c: CoreResourceThread,
s: IpcSender<StorageThreadMsg>,
i: IpcSender<IndexedDBThreadMsg>,
) -> ResourceThreads {
ResourceThreads {
core_thread: c,
storage_thread: s,
idb_thread: i,
}
}
@ -439,6 +447,16 @@ impl IpcSend<CoreResourceMsg> for ResourceThreads {
}
}
impl IpcSend<IndexedDBThreadMsg> for ResourceThreads {
fn send(&self, msg: IndexedDBThreadMsg) -> IpcSendResult {
self.idb_thread.send(msg)
}
fn sender(&self) -> IpcSender<IndexedDBThreadMsg> {
self.idb_thread.clone()
}
}
impl IpcSend<StorageThreadMsg> for ResourceThreads {
fn send(&self, msg: StorageThreadMsg) -> IpcSendResult {
self.storage_thread.send(msg)