-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VPN-5854 - Implement infrastructure for creation of experimental features #8821
Conversation
Yeah, still learning about managing lifetimes without having my hand held by the compiler. (I miss Rust). Turns out I would have to cache the value of the setting in the SettigsGroup object for the previous design to work... I think that would not make much sense so I decided to diverge from the initial design and just expose the getter function itself.
f16f766
to
0f1c097
Compare
0f1c097
to
daa295d
Compare
Intentionally though I will not move other feature files in it just yet, I can do that in a separate PR.
6bd5aa5
to
21615c7
Compare
7671674
to
6455399
Compare
#include "setting.h" | ||
#include "settingsmanager.h" | ||
|
||
class SettingFactory { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should SettingsFactory be folded into SettingManager? Is a separate factory providing value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done and added to the PRE-WORK PR.
Setting* SettingFactory::createOrGetSetting( | ||
const QString& key, std::function<QVariant()> defaultValue, | ||
bool removeWhenReset, bool sensitiveSetting) { | ||
auto s = SettingsManager::getSetting(key); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Consider using a more descriptive variable name for 's'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done and added to the PRE-WORK PR.
* @brief Represents a group of dynamic settings. Dynamic setttings can be | ||
* defined at runtime. | ||
* | ||
* This abstraction serves as an aggregator of underlying storage settings. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice header comments!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Vinoo, means a lot coming from the documentation king himself!
* | ||
* @return QVariant | ||
*/ | ||
Q_INVOKABLE QVariant get(const QString& key) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is getValue a better name? get(key) seems generic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum, I think this falls down to personal preference. If you feel strongly about it, I'll change it. Personally, I prefer it like this. If I do change it, I'd change this in all places, right? i.e. get becomes getValue, set becomes setValue, remove becomes removeValue and so on. Let me know!
|
||
void SettingGroup::addSetting(const QString& key) { | ||
auto settingKey = getSettingKey(key); | ||
auto setting = SettingFactory::createOrGetSetting( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this setting being leaked? Does it need a parent QObject, so it can be deleted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parent is the SettingsManager instance, whose parent it the QApplication.
* actually be removed when `reset` is called. | ||
* @param sensitiveSetting Whether or not settings in this group are | ||
* sensitive settings i.e. settings that must not be logged in plain text. | ||
* @param acceptedKeys When this list has at least one member, only the listed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the enforcement using acceptedKeys needed? If not needed, should it and mayRecord() be removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pre-work for experiments related stuff, which will require an allow list of keys.
sb->m_settings.beginGroup(m_groupKey); | ||
QStringList keys = sb->m_settings.allKeys(); | ||
sb->m_settings.endGroup(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better encapsulation, consider replacing this block with SettingManager::instance()->getKeysInGroup(m_groupKey), which returns the list of keys of Settings in the group.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have addressed this and added it to the PRE-WORK PR. I did not do exactly what you propose here. I'd not like to add public methods to change the underlying settings to the SettingsManager, that is an invitation for mess ups. Instead, I created a connector for the QSettings that is passed to the Setting and SettingGroup for them to be able to access the QSettings. Let me know what you think about the approach.
sb->m_settings.beginGroup(m_groupKey); | ||
QStringList keys = sb->m_settings.allKeys(); | ||
sb->m_settings.remove(""); | ||
sb->m_settings.endGroup(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better encapsulation, consider replacing this with:
keys = SettingManager::instance()->getKeysInGroup(m_groupKey);
SettingManager::instance()->removeSettingsInGroup(m_groupKey)
foreach (const QString& key, keys) { | ||
auto setting = SettingsManager::getSetting(key); | ||
Q_ASSERT(setting); | ||
setting->changed(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the settings in the setting group also be removed from SettingManager.m_registeredSettings?
If so, won't SettingsManager::getSetting(key) fail because the setting has been removed? Appears that the change() signal should be emitted before the settings are removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, great catch. I'll address this and add it to the PRE_WORK PR.
Ok, in hindsight I think it was confusing to open this PR before closing the PRE-WORK PR. All the current comments are related to PRE-WORK code, so I am closing this and will open a new PR once the PRE-WORK PR is complete! |
Ok, this PR is on top of both #8819 and #8820. The only new commit here is f16f766.
The specification for the experimental feature can be found at: https://github.com/mozilla-mobile/mozilla-vpn-client/blob/main/docs/rfcs/0006-cirrus-experiments.md#3-apply-features.
Note I was not able to implement the APIs as specified in the RFC. This is how they will look like:
settingsHolder.onboardingCtaStyleExperiment.get("color");