Merge lp:~jonas-drange/ubuntu-system-settings/security-allow-acceptance-of-here-terms-fixes-1375322 into lp:ubuntu-system-settings

Proposed by Jonas G. Drange
Status: Merged
Approved by: Ken VanDine
Approved revision: 1140
Merged at revision: 1143
Proposed branch: lp:~jonas-drange/ubuntu-system-settings/security-allow-acceptance-of-here-terms-fixes-1375322
Merge into: lp:ubuntu-system-settings
Diff against target: 511 lines (+335/-33)
6 files modified
plugins/security-privacy/CMakeLists.txt (+1/-0)
plugins/security-privacy/Location.qml (+164/-32)
plugins/security-privacy/PageComponent.qml (+2/-1)
plugins/security-privacy/here-terms.qml (+123/-0)
plugins/security-privacy/securityprivacy.cpp (+32/-0)
plugins/security-privacy/securityprivacy.h (+13/-0)
To merge this branch: bzr merge lp:~jonas-drange/ubuntu-system-settings/security-allow-acceptance-of-here-terms-fixes-1375322
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Ken VanDine Needs Fixing
Iain Lane Needs Fixing
Review via email: mp+238419@code.launchpad.net

Commit message

[security/privacy] allow user to change HERE and location detection settings.

Description of the change

Adds a "radio" element to the Location panel under Security and Privacy. This element lets you toggle HERE and location detection.

Note that during testing, I found that when the location indicator dies if you disable gps and toggle location detection. This renders this new panel unusable (ref bug 1382449).

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Terry (mterry) wrote :

Works for me. Jonas, you had suggested that sometimes setHereEnabled doesn't work. But I couldn't get it to fail for me.

As for the code, I will say that I would prefer that rather than having the main ubuntu-system-settings application import Ubuntu.SystemSettings.Wizard.Utils, I'd like the System class to the shared library. Ideally USS wouldn't rely on the wizard (and if you do keep it like this, you'd need to add a debian/control dependency on the wizard).

You had also mentioned just using the AccountsService class we already have, instead of the custom dbus code in the System class. Which is a fair point. I think that would work, but maybe add async versions of the methods too so we could keep that. But that refactoring is not necessary, just a fair cleanup.

Revision history for this message
Iain Lane (laney) wrote :

I added some code comments, and FWIW I agree with Mike on not depending on the wizard from uss.

Not sure why AS is mentioned but indeed the code should go to the helper class, which should be extended if necessary. I remember mentioning that before, probably when this code was added.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Francis Ginther (fginther) wrote :

Mako testing failed due to some hardware downtime, apologies for the inconvenience.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ken VanDine (ken-vandine) wrote :

Tested this on krillin, worked well. We should look at refactoring this if we ever have more location providers. We'll need to make this more more dynamic, and hopefully share the logic with the wizard.

review: Approve
Revision history for this message
Iain Lane (laney) wrote :

On Fri, Oct 17, 2014 at 04:31:28PM -0000, Ken VanDine wrote:
> Review: Approve
>
> Tested this on krillin, worked well. We should look at refactoring this if we ever have more location providers. We'll need to make this more more dynamic, and hopefully share the logic with the wizard.

This is copy and pasted code, so it should be refactored *anyway*.

Also I made some specific suggestions for how the implementation could
be improved, and I still think those are valid.

(not intended to block this MP, but you have my opinion)

--
Iain Lane [ <email address hidden> ]
Debian Developer [ <email address hidden> ]
Ubuntu Developer [ <email address hidden> ]

Revision history for this message
Ken VanDine (ken-vandine) wrote :

> On Fri, Oct 17, 2014 at 04:31:28PM -0000, Ken VanDine wrote:
> > Review: Approve
> >
> > Tested this on krillin, worked well. We should look at refactoring this if
> we ever have more location providers. We'll need to make this more more
> dynamic, and hopefully share the logic with the wizard.
>
> This is copy and pasted code, so it should be refactored *anyway*.
>
> Also I made some specific suggestions for how the implementation could
> be improved, and I still think those are valid.
>
> (not intended to block this MP, but you have my opinion)

Understood, I captured your comments into bug 1382662

>
> --
> Iain Lane [ <email address hidden> ]
> Debian Developer [ <email address hidden> ]
> Ubuntu Developer [ <email address hidden> ]

Revision history for this message
Iain Lane (laney) wrote :

On Fri, Oct 17, 2014 at 07:29:46PM -0000, Ken VanDine wrote:
> > On Fri, Oct 17, 2014 at 04:31:28PM -0000, Ken VanDine wrote:
> > > Review: Approve
> > >
> > > Tested this on krillin, worked well. We should look at refactoring this if
> > we ever have more location providers. We'll need to make this more more
> > dynamic, and hopefully share the logic with the wizard.
> >
> > This is copy and pasted code, so it should be refactored *anyway*.
> >
> > Also I made some specific suggestions for how the implementation could
> > be improved, and I still think those are valid.
> >
> > (not intended to block this MP, but you have my opinion)
>
> Understood, I captured your comments into bug 1382662

Thanks Ken, sorry I didn't review the first implementation.

--
Iain Lane [ <email address hidden> ]
Debian Developer [ <email address hidden> ]
Ubuntu Developer [ <email address hidden> ]

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ken VanDine (ken-vandine) wrote :

In the case where hereInstalled == false, the text in the selector doesn't make much sense:

"Using GPS only (less accurate)"

Which should probably have a different string for that case.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Matthew Paul Thomas (mpt) wrote :

> In the case where hereInstalled == false, the text in the selector doesn't make much sense: "Using GPS only (less accurate)"

Specification updated. <https://wiki.ubuntu.com/Location?action=diff&rev2=13&rev1=12> "If Nokia HERE is installed, the first item should be 'GPS only (less accurate)'. If not, it should be simply 'GPS only', and the second item should not be present."

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/security-privacy/CMakeLists.txt'
2--- plugins/security-privacy/CMakeLists.txt 2014-10-03 13:52:27 +0000
3+++ plugins/security-privacy/CMakeLists.txt 2014-10-21 13:17:19 +0000
4@@ -22,6 +22,7 @@
5 AppAccess.qml
6 AppAccessControl.qml
7 Dash.qml
8+ here-terms.qml
9 Location.qml
10 LockSecurity.qml
11 Ofono.qml
12
13=== modified file 'plugins/security-privacy/Location.qml'
14--- plugins/security-privacy/Location.qml 2014-09-26 14:59:46 +0000
15+++ plugins/security-privacy/Location.qml 2014-10-21 13:17:19 +0000
16@@ -20,22 +20,68 @@
17
18 import GSettings 1.0
19 import QMenuModel 0.1
20-import QtQuick 2.0
21-import Ubuntu.Components 0.1
22+import Qt.labs.folderlistmodel 2.1
23+import QtQuick 2.3
24+import Ubuntu.Components 1.1
25 import Ubuntu.Components.ListItems 0.1 as ListItem
26 import Ubuntu.SystemSettings.SecurityPrivacy 1.0
27 import SystemSettings 1.0
28
29 ItemPage {
30- id: dashPage
31+ id: locationPage
32 title: i18n.tr("Location")
33 flickable: scrollWidget
34
35+ property bool useNone: !useLocation
36+ property bool canLocate: locationActionGroup.enabled.state !== undefined
37+ property bool useLocation: canLocate && locationActionGroup.enabled.state
38+ property bool hereInstalled: securityPrivacy.hereLicensePath !== "" && termsModel.count > 0
39+ property bool useHere: hereInstalled && securityPrivacy.hereEnabled
40+
41+ onUseLocationChanged: {
42+ var newIndex;
43+ if (useLocation) {
44+ newIndex = useHere ? 1 : 0;
45+ } else {
46+ newIndex = detection.model.count - 1;
47+ }
48+ detection.selectedIndex = newIndex;
49+ }
50+
51+ onCanLocateChanged: {
52+ optionsModel.createModel();
53+ }
54+
55+ onHereInstalledChanged: {
56+ optionsModel.createModel();
57+ }
58+
59+ UbuntuSecurityPrivacyPanel {
60+ id: securityPrivacy
61+ }
62+
63+ FolderListModel {
64+ id: termsModel
65+ folder: securityPrivacy.hereLicensePath
66+ nameFilters: ["*.html"]
67+ showDirs: false
68+ showOnlyReadable: true
69+ }
70+
71+ QDBusActionGroup {
72+ id: locationActionGroup
73+ busType: DBus.SessionBus
74+ busName: "com.canonical.indicator.location"
75+ objectPath: "/com/canonical/indicator/location"
76+ property variant enabled: action("location-detection-enabled")
77+ Component.onCompleted: start()
78+ }
79+
80 Flickable {
81 id: scrollWidget
82 anchors.fill: parent
83 contentHeight: contentItem.childrenRect.height
84- boundsBehavior: (contentHeight > dashPage.height) ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
85+ boundsBehavior: (contentHeight > locationPage.height) ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
86 /* Set the direction to workaround https://bugreports.qt-project.org/browse/QTBUG-31905
87 otherwise the UI might end up in a situation where scrolling doesn't work */
88 flickableDirection: Flickable.VerticalFlick
89@@ -44,32 +90,110 @@
90 anchors.left: parent.left
91 anchors.right: parent.right
92
93- QDBusActionGroup {
94- id: locationActionGroup
95- busType: DBus.SessionBus
96- busName: "com.canonical.indicator.location"
97- objectPath: "/com/canonical/indicator/location"
98-
99- property variant enabled: action("location-detection-enabled")
100-
101- Component.onCompleted: start()
102- }
103-
104- ListItem.Standard {
105- text: i18n.tr("Location detection")
106- control: Switch {
107- id: locationOn
108- onClicked: locationActionGroup.enabled.activate()
109- }
110- visible: locationActionGroup.enabled.state !== undefined
111- Component.onCompleted:
112- clicked.connect(locationOn.clicked)
113- }
114-
115- Binding {
116- target: locationOn
117- property: "checked"
118- value: locationActionGroup.enabled.state
119+ ListItem.ItemSelector {
120+ id: detection
121+
122+ /* Helper that toggles location detection and HERE based on
123+ what selector element was tapped. */
124+ function activate (key) {
125+ var usingLocation = locationActionGroup.enabled.state;
126+ if (key === 'none' && usingLocation) {
127+ // turns OFF location detection
128+ locationActionGroup.enabled.activate();
129+ }
130+ if ( (key === 'gps' || key === 'here') && !usingLocation) {
131+ // turns ON location detection
132+ locationActionGroup.enabled.activate();
133+ }
134+ if (locationPage.hereInstalled) {
135+ // toggles whether HERE is enabled
136+ securityPrivacy.hereEnabled = key === 'here';
137+ }
138+ }
139+ property bool allow: selectedIndex !== (model.count - 1)
140+
141+ text: i18n.tr("Let the phone detect your location:")
142+ expanded: true
143+ model: optionsModel
144+ delegate: optionsDelegate
145+ selectedIndex: {
146+ if (model.count === 0) return 0; // re-creating
147+ if (useNone) return model.count - 1;
148+ if (useLocation && !useHere) return 0;
149+ if (useHere && useLocation) return 1;
150+ }
151+ onDelegateClicked: {
152+ activate(model.get(index).key);
153+ }
154+ }
155+
156+ Component {
157+ id: optionsDelegate
158+ OptionSelectorDelegate {
159+
160+ id: dlgt
161+ text: " "
162+ height: label.height
163+ Label {
164+ id: label
165+ anchors {
166+ left: parent.left
167+ right: parent.right
168+ margins: units.gu(2)
169+ rightMargin: units.gu(6)
170+ }
171+ textFormat: Text.StyledText
172+ text: name
173+ wrapMode: Text.WordWrap
174+ verticalAlignment: Text.AlignVCenter
175+ height: contentHeight + units.gu(4)
176+ onLinkActivated: {
177+ pageStack.push(Qt.resolvedUrl(link))
178+ }
179+ onLineLaidOut: {
180+ dlgt.height = label.height
181+ }
182+ }
183+ }
184+ }
185+
186+
187+ ListModel {
188+ id: optionsModel
189+
190+ function createModel () {
191+ clear();
192+
193+ if (canLocate) {
194+ optionsModel.append({
195+ name: hereInstalled ?
196+ i18n.tr("Using GPS only (less accurate)") :
197+ i18n.tr("Using GPS"),
198+ key: "gps"
199+ });
200+ }
201+
202+ if (hereInstalled) {
203+ optionsModel.append({
204+ /* TRANSLATORS: %1 is the resource wherein HERE
205+ terms and conditions reside (typically a qml file).
206+ HERE is a Nokia trademark, so it should probably
207+ not be translated. */
208+ name: i18n.tr("Using GPS, anonymized Wi-Fi and cellular network info.<br>By selecting this option you accept the <a href='%1'>Nokia HERE terms and conditions</a>.").arg("here-terms.qml"),
209+ key: "here"
210+ });
211+ }
212+
213+ optionsModel.append({
214+ name: i18n.tr("Not at all"),
215+ key: "none"
216+ });
217+ }
218+
219+ dynamicRoles: true
220+ Component.onCompleted: {
221+ createModel();
222+ }
223 }
224
225 ListItem.Caption {
226@@ -96,9 +220,11 @@
227 visible: showAllUI /* hide until the information is real */
228 }
229
230+ ListItem.Divider {}
231+
232 ListItem.Standard {
233 text: i18n.tr("Allow access to location:")
234- visible: locationOn.checked
235+ enabled: detection.allow
236 }
237
238 TrustStoreModel {
239@@ -115,9 +241,15 @@
240 checked: model.granted
241 onClicked: trustStoreModel.setEnabled(index, !model.granted)
242 }
243- visible: locationOn.checked
244+ enabled: detection.allow
245 }
246 }
247+
248+ ListItem.Standard {
249+ text: i18n.tr("None requested")
250+ visible: trustStoreModel.count === 0
251+ enabled: false
252+ }
253 }
254
255 }
256
257=== modified file 'plugins/security-privacy/PageComponent.qml'
258--- plugins/security-privacy/PageComponent.qml 2014-09-05 09:01:20 +0000
259+++ plugins/security-privacy/PageComponent.qml 2014-10-21 13:17:19 +0000
260@@ -124,7 +124,7 @@
261 ListItem.Standard {
262 id: securityTitle
263 text: i18n.tr("Security")
264- }
265+ }
266 ListItem.SingleValue {
267 id: lockingControl
268 objectName: "lockingControl"
269@@ -232,6 +232,7 @@
270 }
271 ListItem.SingleValue {
272 id: locationItem
273+ objectName: "locationItem"
274 text: i18n.tr("Location access")
275 value: ""
276 progression: true
277
278=== added file 'plugins/security-privacy/here-terms.qml'
279--- plugins/security-privacy/here-terms.qml 1970-01-01 00:00:00 +0000
280+++ plugins/security-privacy/here-terms.qml 2014-10-21 13:17:19 +0000
281@@ -0,0 +1,123 @@
282+/*
283+ * Copyright (C) 2014 Canonical, Ltd.
284+ *
285+ * This program is free software; you can redistribute it and/or modify
286+ * it under the terms of the GNU General Public License as published by
287+ * the Free Software Foundation; version 3.
288+ *
289+ * This program is distributed in the hope that it will be useful,
290+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
291+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
292+ * GNU General Public License for more details.
293+ *
294+ * You should have received a copy of the GNU General Public License
295+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
296+ */
297+
298+import QtQuick 2.3
299+import Qt.labs.folderlistmodel 2.1
300+import SystemSettings 1.0
301+import Ubuntu.Components 1.1
302+import Ubuntu.SystemSettings.SecurityPrivacy 1.0
303+
304+ItemPage {
305+ title: i18n.tr("Nokia HERE")
306+ id: termsPage
307+
308+ UbuntuSecurityPrivacyPanel {
309+ id: securityPrivacy
310+ }
311+
312+ FolderListModel {
313+ id: termsModel
314+ folder: securityPrivacy.hereLicensePath
315+ nameFilters: ["*.html"]
316+ showDirs: false
317+ showOnlyReadable: true
318+ onCountChanged: loadFileContent()
319+ }
320+
321+ function makeFileName(lang, country) {
322+ return lang + "_" + country + ".html"
323+ }
324+
325+ function defaultCountryForLanguage(lang) {
326+ if (lang === "da") return "DK"
327+ if (lang === "en") return "US"
328+ if (lang === "ko") return "KR"
329+ if (lang === "zh") return "CN"
330+ return lang.toUpperCase()
331+ }
332+
333+ function determineFileName() {
334+ var codes = i18n.language.split(".")[0].split("_")
335+ var defaultCountry = defaultCountryForLanguage(codes[0])
336+ if (codes.count === 1)
337+ codes = [codes[0], defaultCountry]
338+ var perfectMatch = makeFileName(codes[0], codes[1])
339+ var nearMatch = makeFileName(codes[0], defaultCountry)
340+ var nearMatchExists = false
341+
342+ for (var i = 0; i < termsModel.count; i++) {
343+ var fileName = termsModel.get(i, "fileName")
344+ if (fileName == perfectMatch) {
345+ return perfectMatch
346+ } else if (fileName == nearMatch) {
347+ nearMatchExists = true
348+ }
349+ }
350+
351+ if (nearMatchExists) {
352+ return nearMatch
353+ } else {
354+ return makeFileName("en", "US")
355+ }
356+ }
357+
358+ function loadFileContent() {
359+ var xhr = new XMLHttpRequest
360+ xhr.open("GET", securityPrivacy.hereLicensePath + "/" + determineFileName())
361+ console.warn('opening', securityPrivacy.hereLicensePath + "/" + determineFileName())
362+ xhr.onreadystatechange = function() {
363+ if (xhr.readyState == XMLHttpRequest.DONE) {
364+ termsLabel.text = xhr.responseText
365+ }
366+ }
367+ xhr.send()
368+ }
369+ Flickable {
370+ id: scrollWidget
371+ anchors.fill: parent
372+ contentHeight: contentItem.childrenRect.height
373+ boundsBehavior: (contentHeight > termsPage.height) ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
374+ /* Set the direction to workaround https://bugreports.qt-project.org/browse/QTBUG-31905
375+ otherwise the UI might end up in a situation where scrolling doesn't work */
376+ flickableDirection: Flickable.VerticalFlick
377+
378+ Column {
379+ width: scrollWidget.width
380+
381+ Item {
382+ height: units.gu(2)
383+ anchors {
384+ left: parent.left
385+ right: parent.right
386+ }
387+ }
388+
389+ Label {
390+ id: termsLabel
391+ anchors {
392+ margins: units.gu(2)
393+ left: parent.left
394+ right: parent.right
395+ }
396+ wrapMode: Text.Wrap
397+ linkColor: Theme.palette.normal.backgroundText
398+ onLinkActivated: {
399+ Qt.openUrlExternally(link)
400+ }
401+ }
402+ }
403+ }
404+}
405
406=== modified file 'plugins/security-privacy/securityprivacy.cpp'
407--- plugins/security-privacy/securityprivacy.cpp 2014-09-22 15:21:10 +0000
408+++ plugins/security-privacy/securityprivacy.cpp 2014-10-21 13:17:19 +0000
409@@ -30,11 +30,16 @@
410 // FIXME: need to do this better including #include "../../src/i18n.h"
411 // and linking to it
412 #include <libintl.h>
413+
414+
415 QString _(const char *text)
416 {
417 return QString::fromUtf8(dgettext(0, text));
418 }
419
420+#define HERE_IFACE "com.ubuntu.location.providers.here.AccountsService"
421+#define ENABLED_PROP "LicenseAccepted"
422+#define PATH_PROP "LicenseBasePath"
423 #define AS_INTERFACE "com.ubuntu.AccountsService.SecurityPrivacy"
424 #define AS_TOUCH_INTERFACE "com.ubuntu.touch.AccountsService.SecurityPrivacy"
425
426@@ -99,6 +104,12 @@
427 } else if (property == "StatsWelcomeScreen") {
428 Q_EMIT statsWelcomeScreenChanged();
429 }
430+ } else if (interface == HERE_IFACE) {
431+ if (property == ENABLED_PROP) {
432+ Q_EMIT hereEnabledChanged();
433+ } else if (property == PATH_PROP) {
434+ Q_EMIT hereLicensePathChanged();
435+ }
436 }
437 }
438
439@@ -109,6 +120,8 @@
440 Q_EMIT statsWelcomeScreenChanged();
441 Q_EMIT enableLauncherWhileLockedChanged();
442 Q_EMIT enableIndicatorsWhileLockedChanged();
443+ Q_EMIT hereEnabledChanged();
444+ Q_EMIT hereLicensePathChanged();
445 }
446
447 bool SecurityPrivacy::getStatsWelcomeScreen()
448@@ -462,6 +475,25 @@
449 }
450 }
451
452+bool SecurityPrivacy::hereEnabled()
453+{
454+ return m_accountsService.getUserProperty(HERE_IFACE,
455+ ENABLED_PROP).toBool();
456+}
457+
458+void SecurityPrivacy::setHereEnabled(bool enabled)
459+{
460+ m_accountsService.setUserProperty(HERE_IFACE, ENABLED_PROP,
461+ QVariant::fromValue(enabled));
462+ Q_EMIT(hereEnabledChanged());
463+}
464+
465+QString SecurityPrivacy::hereLicensePath()
466+{
467+ return m_accountsService.getUserProperty(HERE_IFACE,
468+ PATH_PROP).toString();
469+}
470+
471 void managerLoaded(GObject *object,
472 GParamSpec *pspec,
473 gpointer user_data)
474
475=== modified file 'plugins/security-privacy/securityprivacy.h'
476--- plugins/security-privacy/securityprivacy.h 2014-08-29 05:19:03 +0000
477+++ plugins/security-privacy/securityprivacy.h 2014-10-21 13:17:19 +0000
478@@ -59,6 +59,13 @@
479 Q_PROPERTY (SecurityType securityType
480 READ getSecurityType
481 NOTIFY securityTypeChanged)
482+ Q_PROPERTY (bool hereEnabled
483+ READ hereEnabled
484+ WRITE setHereEnabled
485+ NOTIFY hereEnabledChanged)
486+ Q_PROPERTY (QString hereLicensePath
487+ READ hereLicensePath
488+ NOTIFY hereLicensePathChanged)
489
490 public:
491 enum SecurityType {
492@@ -80,6 +87,10 @@
493 void setEnableIndicatorsWhileLocked(bool enabled);
494 SecurityType getSecurityType();
495
496+ bool hereEnabled();
497+ void setHereEnabled(bool enabled);
498+ QString hereLicensePath();
499+
500 // Returns error text, if an error occurred
501 Q_INVOKABLE QString setSecurity(QString oldValue, QString value, SecurityType type);
502 Q_INVOKABLE bool trySetSecurity(SecurityType type);
503@@ -94,6 +105,8 @@
504 void enableLauncherWhileLockedChanged();
505 void enableIndicatorsWhileLockedChanged();
506 void securityTypeChanged();
507+ void hereEnabledChanged();
508+ void hereLicensePathChanged();
509
510 private:
511 void loadUser();

Subscribers

People subscribed via source and target branches