Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions crates/matrix-sdk-indexeddb/src/event_cache_store/builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright 2025 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

use std::sync::Arc;

use matrix_sdk_base::event_cache::store::MemoryStore;
use matrix_sdk_store_encryption::StoreCipher;
use web_sys::DomException;

use crate::{
event_cache_store::{
error::IndexeddbEventCacheStoreError, migrations::open_and_upgrade_db,
serializer::IndexeddbEventCacheStoreSerializer, IndexeddbEventCacheStore,
},
serializer::IndexeddbSerializer,
};

/// A type for conveniently building an [`IndexeddbEventCacheStore`]
pub struct IndexeddbEventCacheStoreBuilder {
// The name of the IndexedDB database which will be opened
database_name: String,
// The store cipher, if any, to use when encrypting data
// before it is persisted to the IndexedDB database
store_cipher: Option<Arc<StoreCipher>>,
}

impl Default for IndexeddbEventCacheStoreBuilder {
fn default() -> Self {
Self { database_name: Self::DEFAULT_DATABASE_NAME.to_owned(), store_cipher: None }
}
}

impl IndexeddbEventCacheStoreBuilder {
/// The default name of the IndexedDB database used to back the
/// [`IndexeddbEventCacheStore`]
pub const DEFAULT_DATABASE_NAME: &'static str = "event_cache";

/// Sets the name of the IndexedDB database which will be opened. This
/// defaults to [`Self::DEFAULT_DATABASE_NAME`].
pub fn database_name(mut self, name: String) -> Self {
self.database_name = name;
self
}

/// Sets the store cipher to use when encrypting data before it is persisted
/// to the IndexedDB database. By default, no store cipher is used -
/// i.e., data is not encrypted before it is persisted.
pub fn store_cipher(mut self, store_cipher: Arc<StoreCipher>) -> Self {
self.store_cipher = Some(store_cipher);
self
}

/// Opens the IndexedDB database with the provided name. If successfully
/// opened, builds the [`IndexeddbEventCacheStore`] with that database
/// and the provided store cipher.
pub async fn build(self) -> Result<IndexeddbEventCacheStore, IndexeddbEventCacheStoreError> {
Ok(IndexeddbEventCacheStore {
inner: open_and_upgrade_db(&self.database_name).await?,
serializer: IndexeddbEventCacheStoreSerializer::new(IndexeddbSerializer::new(
self.store_cipher,
)),
memory_store: MemoryStore::new(),
})
}
}
52 changes: 51 additions & 1 deletion crates/matrix-sdk-indexeddb/src/event_cache_store/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License

use matrix_sdk_base::{SendOutsideWasm, SyncOutsideWasm};
use matrix_sdk_base::{
event_cache::store::{EventCacheStore, EventCacheStoreError, MemoryStore},
SendOutsideWasm, SyncOutsideWasm,
};
use serde::de::Error;
use thiserror::Error;

use crate::event_cache_store::transaction::IndexeddbEventCacheStoreTransactionError;

/// A trait that combines the necessary traits needed for asynchronous runtimes,
/// but excludes them when running in a web environment - i.e., when
Expand All @@ -21,3 +28,46 @@ pub trait AsyncErrorDeps: std::error::Error + SendOutsideWasm + SyncOutsideWasm

impl<T> AsyncErrorDeps for T where T: std::error::Error + SendOutsideWasm + SyncOutsideWasm + 'static
{}

#[derive(Debug, Error)]
pub enum IndexeddbEventCacheStoreError {
#[error("DomException {name} ({code}): {message}")]
DomException { name: String, message: String, code: u16 },
#[error("transaction: {0}")]
Transaction(#[from] IndexeddbEventCacheStoreTransactionError),
#[error("media store: {0}")]
MemoryStore(<MemoryStore as EventCacheStore>::Error),
}

impl From<web_sys::DomException> for IndexeddbEventCacheStoreError {
fn from(value: web_sys::DomException) -> IndexeddbEventCacheStoreError {
IndexeddbEventCacheStoreError::DomException {
name: value.name(),
message: value.message(),
code: value.code(),
}
}
}

impl From<IndexeddbEventCacheStoreError> for EventCacheStoreError {
fn from(value: IndexeddbEventCacheStoreError) -> Self {
match value {
IndexeddbEventCacheStoreError::DomException { .. } => {
Self::InvalidData { details: value.to_string() }
}
IndexeddbEventCacheStoreError::Transaction(ref inner) => match inner {
IndexeddbEventCacheStoreTransactionError::DomException { .. } => {
Self::InvalidData { details: value.to_string() }
}
IndexeddbEventCacheStoreTransactionError::Serialization(e) => {
Self::Serialization(serde_json::Error::custom(e.to_string()))
}
IndexeddbEventCacheStoreTransactionError::ItemIsNotUnique
| IndexeddbEventCacheStoreTransactionError::ItemNotFound => {
Self::InvalidData { details: value.to_string() }
}
},
IndexeddbEventCacheStoreError::MemoryStore(inner) => inner,
}
}
}
Loading
Loading