diff options
Diffstat (limited to 'Userland/Services/ConfigServer')
4 files changed, 79 insertions, 15 deletions
diff --git a/Userland/Services/ConfigServer/ClientConnection.cpp b/Userland/Services/ConfigServer/ClientConnection.cpp index 3551a1af5b..246a95e10f 100644 --- a/Userland/Services/ConfigServer/ClientConnection.cpp +++ b/Userland/Services/ConfigServer/ClientConnection.cpp @@ -12,6 +12,25 @@ namespace ConfigServer { static HashMap<int, RefPtr<ClientConnection>> s_connections; +struct CachedDomain { + String domain; + NonnullRefPtr<Core::ConfigFile> config; +}; + +static HashMap<String, NonnullOwnPtr<CachedDomain>> s_cache; + +static Core::ConfigFile& ensure_domain_config(String const& domain) +{ + auto it = s_cache.find(domain); + if (it != s_cache.end()) + return *it->value->config; + + auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes); + auto cache_entry = make<CachedDomain>(domain, config); + s_cache.set(domain, move(cache_entry)); + return *config; +} + ClientConnection::ClientConnection(NonnullRefPtr<Core::LocalSocket> client_socket, int client_id) : IPC::ClientConnection<ConfigClientEndpoint, ConfigServerEndpoint>(*this, move(client_socket), client_id) { @@ -38,6 +57,16 @@ void ClientConnection::pledge_domains(Vector<String> const& domains) m_pledged_domains.set(domain); } +void ClientConnection::monitor_domain(String const& domain) +{ + if (m_has_pledged && !m_pledged_domains.contains(domain)) { + did_misbehave("Attempt to monitor non-pledged domain"); + return; + } + + m_monitored_domains.set(domain); +} + bool ClientConnection::validate_access(String const& domain, String const& group, String const& key) { if (!m_has_pledged) @@ -53,10 +82,10 @@ Messages::ConfigServer::ReadStringValueResponse ClientConnection::read_string_va if (!validate_access(domain, group, key)) return nullptr; - auto config = Core::ConfigFile::open_for_app(domain); - if (!config->has_key(group, key)) + auto& config = ensure_domain_config(domain); + if (!config.has_key(group, key)) return Optional<String> {}; - return Optional<String> { config->read_entry(group, key) }; + return Optional<String> { config.read_entry(group, key) }; } Messages::ConfigServer::ReadI32ValueResponse ClientConnection::read_i32_value(String const& domain, String const& group, String const& key) @@ -64,10 +93,10 @@ Messages::ConfigServer::ReadI32ValueResponse ClientConnection::read_i32_value(St if (!validate_access(domain, group, key)) return nullptr; - auto config = Core::ConfigFile::open_for_app(domain); - if (!config->has_key(group, key)) + auto& config = ensure_domain_config(domain); + if (!config.has_key(group, key)) return Optional<i32> {}; - return Optional<i32> { config->read_num_entry(group, key) }; + return Optional<i32> { config.read_num_entry(group, key) }; } Messages::ConfigServer::ReadBoolValueResponse ClientConnection::read_bool_value(String const& domain, String const& group, String const& key) @@ -75,10 +104,10 @@ Messages::ConfigServer::ReadBoolValueResponse ClientConnection::read_bool_value( if (!validate_access(domain, group, key)) return nullptr; - auto config = Core::ConfigFile::open_for_app(domain); - if (!config->has_key(group, key)) + auto& config = ensure_domain_config(domain); + if (!config.has_key(group, key)) return Optional<bool> {}; - return Optional<bool> { config->read_bool_entry(group, key) }; + return Optional<bool> { config.read_bool_entry(group, key) }; } void ClientConnection::write_string_value(String const& domain, String const& group, String const& key, String const& value) @@ -86,8 +115,17 @@ void ClientConnection::write_string_value(String const& domain, String const& gr if (!validate_access(domain, group, key)) return; - auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes); - config->write_entry(group, key, value); + auto& config = ensure_domain_config(domain); + + if (config.has_key(group, key) && config.read_entry(group, key) == value) + return; + + config.write_entry(group, key, value); + + for (auto& it : s_connections) { + if (it.value != this && it.value->m_monitored_domains.contains(domain)) + it.value->async_notify_changed_string_value(domain, group, key, value); + } } void ClientConnection::write_i32_value(String const& domain, String const& group, String const& key, i32 value) @@ -95,8 +133,17 @@ void ClientConnection::write_i32_value(String const& domain, String const& group if (!validate_access(domain, group, key)) return; - auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes); - config->write_num_entry(group, key, value); + auto& config = ensure_domain_config(domain); + + if (config.has_key(group, key) && config.read_num_entry(group, key) == value) + return; + + config.write_num_entry(group, key, value); + + for (auto& it : s_connections) { + if (it.value != this && it.value->m_monitored_domains.contains(domain)) + it.value->async_notify_changed_i32_value(domain, group, key, value); + } } void ClientConnection::write_bool_value(String const& domain, String const& group, String const& key, bool value) @@ -104,8 +151,17 @@ void ClientConnection::write_bool_value(String const& domain, String const& grou if (!validate_access(domain, group, key)) return; - auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes); - config->write_bool_entry(group, key, value); + auto& config = ensure_domain_config(domain); + + if (config.has_key(group, key) && config.read_bool_entry(group, key) == value) + return; + + config.write_bool_entry(group, key, value); + + for (auto& it : s_connections) { + if (it.value != this && it.value->m_monitored_domains.contains(domain)) + it.value->async_notify_changed_bool_value(domain, group, key, value); + } } } diff --git a/Userland/Services/ConfigServer/ClientConnection.h b/Userland/Services/ConfigServer/ClientConnection.h index cdbc53ab64..55bd3ebb9c 100644 --- a/Userland/Services/ConfigServer/ClientConnection.h +++ b/Userland/Services/ConfigServer/ClientConnection.h @@ -24,6 +24,7 @@ private: explicit ClientConnection(NonnullRefPtr<Core::LocalSocket>, int client_id); virtual void pledge_domains(Vector<String> const&) override; + virtual void monitor_domain(String const&) override; virtual Messages::ConfigServer::ReadStringValueResponse read_string_value([[maybe_unused]] String const& domain, [[maybe_unused]] String const& group, [[maybe_unused]] String const& key) override; virtual Messages::ConfigServer::ReadI32ValueResponse read_i32_value([[maybe_unused]] String const& domain, [[maybe_unused]] String const& group, [[maybe_unused]] String const& key) override; virtual Messages::ConfigServer::ReadBoolValueResponse read_bool_value([[maybe_unused]] String const& domain, [[maybe_unused]] String const& group, [[maybe_unused]] String const& key) override; @@ -35,6 +36,8 @@ private: bool m_has_pledged { false }; HashTable<String> m_pledged_domains; + + HashTable<String> m_monitored_domains; }; } diff --git a/Userland/Services/ConfigServer/ConfigClient.ipc b/Userland/Services/ConfigServer/ConfigClient.ipc index bd0318b3ad..d8436b671d 100644 --- a/Userland/Services/ConfigServer/ConfigClient.ipc +++ b/Userland/Services/ConfigServer/ConfigClient.ipc @@ -1,3 +1,6 @@ endpoint ConfigClient { + notify_changed_string_value(String domain, String group, String key, String value) =| + notify_changed_i32_value(String domain, String group, String key, i32 value) =| + notify_changed_bool_value(String domain, String group, String key, bool value) =| } diff --git a/Userland/Services/ConfigServer/ConfigServer.ipc b/Userland/Services/ConfigServer/ConfigServer.ipc index 9ce1bbc70a..055e85241f 100644 --- a/Userland/Services/ConfigServer/ConfigServer.ipc +++ b/Userland/Services/ConfigServer/ConfigServer.ipc @@ -2,6 +2,8 @@ endpoint ConfigServer { pledge_domains(Vector<String> domains) =| + monitor_domain(String domain) =| + read_string_value(String domain, String group, String key) => (Optional<String> value) read_i32_value(String domain, String group, String key) => (Optional<i32> value) read_bool_value(String domain, String group, String key) => (Optional<bool> value) |