Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[devicelock] Add read-only settings for requiring device lock, and av…
…ailable settings values. Contributes to JB#37377
  • Loading branch information
adenexter committed Mar 29, 2017
1 parent 288f7d7 commit 7b091ce
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 33 deletions.
34 changes: 33 additions & 1 deletion src/nemo-devicelock/devicelocksettings.cpp
Expand Up @@ -70,6 +70,10 @@ DeviceLockSettings::DeviceLockSettings(QObject *parent)
this, &DeviceLockSettings::inputIsKeyboardChanged);
connect(m_settings.data(), &SettingsWatcher::currentCodeIsDigitOnlyChanged,
this, &DeviceLockSettings::currentCodeIsDigitOnlyChanged);
connect(m_settings.data(), &SettingsWatcher::maximumAutomaticLockingChanged,
this, &DeviceLockSettings::maximumAutomaticLockingChanged);
connect(m_settings.data(), &SettingsWatcher::absoluteMaximumAttemptsChanged,
this, &DeviceLockSettings::absoluteMaximumAttemptsChanged);

m_connection->onConnected(this, [this] {
connected();
Expand Down Expand Up @@ -259,11 +263,39 @@ bool DeviceLockSettings::isHomeEncrypted() const
return m_settings->isHomeEncrypted;
}

/*!
\property NemoDeviceLock::DeviceLockSettings::maximumAutomaticLocking
This property holds the maximum possible value of \l automaticLocking. If theres is no limit
this will be equal to -1.
*/

int DeviceLockSettings::maximumAutomaticLocking() const
{
return m_settings->maximumAutomaticLocking;
}

/*!
\property NemoDeviceLockSettings::absoluteMaximumAttempts
This property holds the maximum possible value of \l maximumAttempts. If theres is no limit
this will be equal to -1.
*/

int DeviceLockSettings::absoluteMaximumAttempts() const
{
return m_settings->absoluteMaximumAttempts;
}

void DeviceLockSettings::changeSetting(
const QVariant &authenticationToken, const QString &key, const QVariant &value)
{
if (m_authorization.status() == Authorization::ChallengeIssued) {
call(QStringLiteral("ChangeSetting"), m_localPath, authenticationToken, key, value);
call(QStringLiteral("ChangeSetting"),
m_localPath,
authenticationToken,
QStringLiteral("/desktop/nemo/devicelock/") + key,
value);
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/nemo-devicelock/devicelocksettings.h
Expand Up @@ -52,6 +52,8 @@ class NEMODEVICELOCK_EXPORT DeviceLockSettings : public QObject, private Connect
Q_PROPERTY(bool inputIsKeyboard READ inputIsKeyboard NOTIFY inputIsKeyboardChanged)
Q_PROPERTY(bool currentCodeIsDigitOnly READ currentCodeIsDigitOnly NOTIFY currentCodeIsDigitOnlyChanged)
Q_PROPERTY(bool homeEncrypted READ isHomeEncrypted CONSTANT)
Q_PROPERTY(int maximumAutomaticLocking READ maximumAutomaticLocking NOTIFY maximumAutomaticLockingChanged)
Q_PROPERTY(int absoluteMaximumAttempts READ absoluteMaximumAttempts NOTIFY absoluteMaximumAttemptsChanged)
public:
explicit DeviceLockSettings(QObject *parent = nullptr);
~DeviceLockSettings();
Expand Down Expand Up @@ -80,6 +82,9 @@ class NEMODEVICELOCK_EXPORT DeviceLockSettings : public QObject, private Connect

bool isHomeEncrypted() const;

int maximumAutomaticLocking() const;
int absoluteMaximumAttempts() const;

signals:
void automaticLockingChanged();
void maximumAttemptsChanged();
Expand All @@ -88,6 +93,8 @@ class NEMODEVICELOCK_EXPORT DeviceLockSettings : public QObject, private Connect
void showNotificationsChanged();
void inputIsKeyboardChanged();
void currentCodeIsDigitOnlyChanged();
void maximumAutomaticLockingChanged();
void absoluteMaximumAttemptsChanged();

private:
inline void changeSetting(
Expand Down
17 changes: 17 additions & 0 deletions src/nemo-devicelock/devicereset.cpp
Expand Up @@ -31,6 +31,7 @@
*/

#include "devicereset.h"
#include "private/settingswatcher.h"

namespace NemoDeviceLock
{
Expand Down Expand Up @@ -60,7 +61,11 @@ DeviceReset::DeviceReset(QObject *parent)
QStringLiteral("org.nemomobile.devicelock.DeviceReset"))
, m_authorization(m_localPath, path())
, m_authorizationAdaptor(&m_authorization, this)
, m_settings(SettingsWatcher::instance())
{
connect(m_settings.data(), &SettingsWatcher::supportedDeviceResetOptionsChanged,
this, &DeviceReset::supportedOptionsChanged);

m_connection->onConnected(this, [this] {
connected();
});
Expand Down Expand Up @@ -90,6 +95,18 @@ Authorization *DeviceReset::authorization()
return &m_authorization;
}

/*!
\property NemoDeviceLock::DeviceReset::supportedOptions
This property holds the supported value for the options argument of clear device.
Values not in this set will be ignored and should not be selectable in the UI.
*/
DeviceReset::Options DeviceReset::supportedOptions() const
{
return m_settings->supportedDeviceResetOptions;
}

/*!
Requests a reset of the device to factory settings.
Expand Down
8 changes: 8 additions & 0 deletions src/nemo-devicelock/devicereset.h
Expand Up @@ -38,16 +38,20 @@
namespace NemoDeviceLock
{

class SettingsWatcher;

class NEMODEVICELOCK_EXPORT DeviceReset : public QObject, private ConnectionClient
{
Q_OBJECT
Q_PROPERTY(NemoDeviceLock::Authorization *authorization READ authorization CONSTANT)
Q_PROPERTY(Options supportedOptions READ supportedOptions NOTIFY supportedOptionsChanged)
public:
enum Option {
Shutdown = 0x00,
Reboot = 0x01,
WipePartitions = 0x02
};
Q_ENUM(Option)
Q_DECLARE_FLAGS(Options, Option)
Q_FLAG(Options)

Expand All @@ -56,9 +60,12 @@ class NEMODEVICELOCK_EXPORT DeviceReset : public QObject, private ConnectionClie

Authorization *authorization();

Options supportedOptions() const;

Q_INVOKABLE void clearDevice(const QVariant &authenticationToken, Options options = Shutdown);

signals:
void supportedOptionsChanged();
void clearingDevice();
void clearDeviceError();

Expand All @@ -67,6 +74,7 @@ class NEMODEVICELOCK_EXPORT DeviceReset : public QObject, private ConnectionClie

ClientAuthorization m_authorization;
ClientAuthorizationAdaptor m_authorizationAdaptor;
QExplicitlySharedDataPointer<SettingsWatcher> m_settings;
};

}
Expand Down
123 changes: 91 additions & 32 deletions src/nemo-devicelock/private/settingswatcher.cpp
Expand Up @@ -47,17 +47,35 @@
namespace NemoDeviceLock
{

const char * const SettingsWatcher::automaticLockingKey = "/desktop/nemo/devicelock/automatic_locking";
const char * const SettingsWatcher::minimumLengthKey = "/desktop/nemo/devicelock/code_min_length";
const char * const SettingsWatcher::maximumLengthKey = "/desktop/nemo/devicelock/code_max_length";
const char * const SettingsWatcher::maximumAttemptsKey = "/desktop/nemo/devicelock/maximum_attempts";
const char * const SettingsWatcher::currentAttemptsKey = "/desktop/nemo/devicelock/current_attempts";
const char * const SettingsWatcher::peekingAllowedKey = "/desktop/nemo/devicelock/peeking_allowed";
const char * const SettingsWatcher::sideloadingAllowedKey = "/desktop/nemo/devicelock/sideloading_allowed";
const char * const SettingsWatcher::showNotificationsKey = "/desktop/nemo/devicelock/show_notification";
const char * const SettingsWatcher::inputIsKeyboardKey = "/desktop/nemo/devicelock/code_input_is_keyboard";
const char * const SettingsWatcher::currentIsDigitOnlyKey = "/desktop/nemo/devicelock/code_current_is_digit_only";
const char * const SettingsWatcher::isHomeEncryptedKey = "/desktop/nemo/devicelock/encrypt_home";
QMetaEnum resolveMetaEnum(const QMetaObject *metaObject, const char *name)
{
const int index = metaObject->indexOfEnumerator(name);
return index != -1 ? metaObject->enumerator(index) : QMetaEnum();
}

int flagsFromString(const QMetaEnum &enumeration, const char *string)
{
int flags = 0;
for (const QByteArray &key : QByteArray(string).split(',')) {
const int value = enumeration.keyToValue(key);
if (value != -1) {
flags |= value;
}
}
return flags;
}

const char * const SettingsWatcher::automaticLockingKey = "automatic_locking";
const char * const SettingsWatcher::minimumLengthKey = "code_min_length";
const char * const SettingsWatcher::maximumLengthKey = "code_max_length";
const char * const SettingsWatcher::maximumAttemptsKey = "maximum_attempts";
const char * const SettingsWatcher::currentAttemptsKey = "current_attempts";
const char * const SettingsWatcher::peekingAllowedKey = "peeking_allowed";
const char * const SettingsWatcher::sideloadingAllowedKey = "sideloading_allowed";
const char * const SettingsWatcher::showNotificationsKey = "show_notification";
const char * const SettingsWatcher::inputIsKeyboardKey = "code_input_is_keyboard";
const char * const SettingsWatcher::currentIsDigitOnlyKey = "code_current_is_digit_only";
const char * const SettingsWatcher::isHomeEncryptedKey = "encrypt_home";

SettingsWatcher *SettingsWatcher::sharedInstance = nullptr;

Expand All @@ -71,9 +89,13 @@ SettingsWatcher::SettingsWatcher(QObject *parent)
, peekingAllowed(1)
, sideloadingAllowed(-1)
, showNotifications(1)
, maximumAutomaticLocking(-1)
, absoluteMaximumAttempts(-1)
, supportedDeviceResetOptions(DeviceReset::Reboot)
, inputIsKeyboard(false)
, currentCodeIsDigitOnly(true)
, isHomeEncrypted(false)
, codeIsMandatory(false)
, m_settingsPath(QStringLiteral("/usr/share/lipstick/devicelock/devicelock_settings.conf"))
, m_watch(-1)
{
Expand Down Expand Up @@ -131,8 +153,26 @@ bool SettingsWatcher::event(QEvent *event)
}
}

template <typename T> T readConfigValue(GKeyFile *config, const char *group, const char *key, T defaultValue)
{
GError *error = nullptr;
gchar *string = g_key_file_get_string(config, group, key, &error);
if (error) {
if (error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND
&& error->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND) {
qCWarning(devicelock) << "Error reading" << group << key << error->message;
}
g_error_free(error);

return defaultValue;
} else {
const T value = settingsValueFromString<T>(string);

g_free(string);

template <typename T> T readConfigValue(GKeyFile *config, const char *group, const char *key, T defaultValue);
return value;
}
}

template <> int readConfigValue<int>(GKeyFile *config, const char *group, const char *key, int defaultValue)
{
Expand Down Expand Up @@ -169,46 +209,65 @@ template <> bool readConfigValue<bool>(
}
}


template <typename T>
static void read(
GKeyFile *settings,
SettingsWatcher *watcher,
const char *group,
const char *key,
T defaultValue,
T (SettingsWatcher::*member),
T *member,
void (SettingsWatcher::*changed)() = nullptr)
{
const T value = readConfigValue<T>(
settings,
"desktop",
QByteArray(key + 9 /* /desktop/ */).replace('/', '\\').constData(),
defaultValue);
const T value = readConfigValue<T>(settings, group, key, defaultValue);

if (watcher->*member != value) {
watcher->*member = value;
if (*member != value) {
*member = value;
if (changed) {
emit (watcher->*changed)();
}
}
}

template <typename T>
static void read(
GKeyFile *settings,
SettingsWatcher *watcher,
const char *key,
T defaultValue,
T *member,
void (SettingsWatcher::*changed)() = nullptr)
{
read(settings,
watcher,
"desktop",
(QByteArrayLiteral("nemo\\devicelock\\") + key).constData(),
defaultValue,
member,
changed);
}

void SettingsWatcher::reloadSettings()
{
GKeyFile * const settings = g_key_file_new();
g_key_file_load_from_file(settings, m_settingsPath.toUtf8().constData(), G_KEY_FILE_NONE, 0);

read(settings, this, automaticLockingKey, 5, &SettingsWatcher::automaticLocking, &SettingsWatcher::automaticLockingChanged);
read(settings, this, minimumLengthKey, 5, &SettingsWatcher::minimumLength, &SettingsWatcher::minimumLengthChanged);
read(settings, this, maximumLengthKey, 42, &SettingsWatcher::maximumLength, &SettingsWatcher::maximumLengthChanged);
read(settings, this, maximumAttemptsKey, -1, &SettingsWatcher::maximumAttempts, &SettingsWatcher::maximumAttemptsChanged);
read(settings, this, currentAttemptsKey, 0, &SettingsWatcher::currentAttempts, &SettingsWatcher::currentAttemptsChanged);
read(settings, this, peekingAllowedKey, 1, &SettingsWatcher::peekingAllowed, &SettingsWatcher::peekingAllowedChanged);
read(settings, this, sideloadingAllowedKey, -1, &SettingsWatcher::sideloadingAllowed, &SettingsWatcher::sideloadingAllowedChanged);
read(settings, this, showNotificationsKey, 1, &SettingsWatcher::showNotifications, &SettingsWatcher::showNotificationsChanged);
read(settings, this, inputIsKeyboardKey, false, &SettingsWatcher::inputIsKeyboard, &SettingsWatcher::inputIsKeyboardChanged);
read(settings, this, currentIsDigitOnlyKey, true, &SettingsWatcher::currentCodeIsDigitOnly, &SettingsWatcher::currentCodeIsDigitOnlyChanged);
read(settings, this, isHomeEncryptedKey, false, &SettingsWatcher::isHomeEncrypted);
read(settings, this, automaticLockingKey, 5, &automaticLocking, &SettingsWatcher::automaticLockingChanged);
read(settings, this, minimumLengthKey, 5, &minimumLength, &SettingsWatcher::minimumLengthChanged);
read(settings, this, maximumLengthKey, 42, &maximumLength, &SettingsWatcher::maximumLengthChanged);
read(settings, this, maximumAttemptsKey, -1, &maximumAttempts, &SettingsWatcher::maximumAttemptsChanged);
read(settings, this, currentAttemptsKey, 0, &currentAttempts, &SettingsWatcher::currentAttemptsChanged);
read(settings, this, peekingAllowedKey, 1, &peekingAllowed, &SettingsWatcher::peekingAllowedChanged);
read(settings, this, sideloadingAllowedKey, -1, &sideloadingAllowed, &SettingsWatcher::sideloadingAllowedChanged);
read(settings, this, showNotificationsKey, 1, &showNotifications, &SettingsWatcher::showNotificationsChanged);
read(settings, this, inputIsKeyboardKey, false, &inputIsKeyboard, &SettingsWatcher::inputIsKeyboardChanged);
read(settings, this, currentIsDigitOnlyKey, true, &currentCodeIsDigitOnly, &SettingsWatcher::currentCodeIsDigitOnlyChanged);
read(settings, this, isHomeEncryptedKey, false, &isHomeEncrypted);

read(settings, this, "maximum_automatic_locking", -1, &maximumAutomaticLocking, &SettingsWatcher::maximumAutomaticLockingChanged);
read(settings, this, "absolute_maximum_attempts", -1, &absoluteMaximumAttempts, &SettingsWatcher::absoluteMaximumAttemptsChanged);
read(settings, this, "supported_device_reset_options", DeviceReset::Options(DeviceReset::Reboot), &supportedDeviceResetOptions, &SettingsWatcher::supportedDeviceResetOptionsChanged);
read(settings, this, "code_is_mandatory", false, &codeIsMandatory, &SettingsWatcher::codeIsMandatoryChanged);

g_key_file_free(settings);
}
Expand Down

0 comments on commit 7b091ce

Please sign in to comment.