Merge lp:~kissiel/checkbox/confined-permission-control into lp:checkbox

Proposed by Maciej Kisielewski
Status: Merged
Approved by: Maciej Kisielewski
Approved revision: 4124
Merged at revision: 4114
Proposed branch: lp:~kissiel/checkbox/confined-permission-control
Merge into: lp:checkbox
Diff against target: 316 lines (+129/-24)
8 files modified
checkbox-touch/build-me (+47/-0)
checkbox-touch/checkbox-touch.qml (+1/-1)
checkbox-touch/components/CheckboxTouchApplication.qml (+6/-0)
checkbox-touch/components/QmlConfinedPage.qml (+28/-4)
checkbox-touch/confinement/generate.py (+20/-16)
checkbox-touch/manifest.json (+2/-2)
checkbox-touch/py/checkbox_touch.py (+24/-1)
plainbox/plainbox/data/plainbox-qml-modules/Plainbox/QmlJob.qml (+1/-0)
To merge this branch: bzr merge lp:~kissiel/checkbox/confined-permission-control
Reviewer Review Type Date Requested Status
Zygmunt Krynicki (community) Approve
Review via email: mp+278066@code.launchpad.net

Description of the change

This MR brings a possibility of dropping specified permissions for confined tests in checkbox-converged.

bf3ffb4 checkbox-touch: fix missing test information for native jobs
eb2efd7 checkbox-touch: bump version in py backend
57cd0ed checkbox-touch: correct version in manifest to match PB format
0926cde checkbox-touch: add dropPersmission function
ac4d6a3 plainbox:data:plainbox-qml-modules: add 'clearedPermissions' field
4c7a6ff checkbox-touch: add logic for dropping permissions for confined tests
3367259 checkbox-touch: rename generate-confinement to make it importable
3656f0b checkbox-touch:confinement: make generate_confinement return the hook
c7a4f37 checkbox-touch:confinement: do not jsonize by default
7ddda80 checkbox-touch:confinement: fix PEP-8 issues
ccd2c6a checkbox-touch:build-me: add building confinement

To post a comment you must log in.
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

Most things are okay but I'd like to see something better for the database handling

review: Needs Fixing
Revision history for this message
Maciej Kisielewski (kissiel) wrote :

> Most things are okay but I'd like to see something better for the database
> handling

As for DBs being locked, if the timeout hits, this will get propagated to UI.
For proper cleanup, I addded try, finally.

Todo for XDG stuff added.

4119. By Maciej Kisielewski

checkbox-touch: add logic for dropping permissions for confined tests

This patch adds the logic that pulls information from the test's qml file about
which permissions to clear, and calls appropriate bits.
To extract this info we first instantiate the QmlJob object in a fake container
Item, so te field is initiated as test author specified, then immedietaly (and
synchronously) destroyed, so all resources are (not sure about that :)) freed.
Signed-off-by: Maciej Kisielewski <email address hidden>

4120. By Maciej Kisielewski

checkbox-touch: rename generate-confinement to make it importable

Signed-off-by: Maciej Kisielewski <email address hidden>

4121. By Maciej Kisielewski

checkbox-touch:confinement: make generate_confinement return the hook

Signed-off-by: Maciej Kisielewski <email address hidden>

4122. By Maciej Kisielewski

checkbox-touch:confinement: do not jsonize by default

This patch makes generate result hook object instead of strigified json. This
makes easier to handle marshalling everything together in a calling function.

Signed-off-by: Maciej Kisielewski <email address hidden>

4123. By Maciej Kisielewski

checkbox-touch:confinement: fix PEP-8 issues

Signed-off-by: Maciej Kisielewski <email address hidden>

4124. By Maciej Kisielewski

checkbox-touch:build-me: add building confinement

This patch runs the task of building files necessary for confined qml tests to
work while building click package.

From now on, after build-me successfully validates all the included providers,
it loads job units from them, checks if there's any qml confined job, and
generates appropriate files necessary to run those. It also overwrites the
manifest.json file, to include the new hooks.

Signed-off-by: Maciej Kisielewski <email address hidden>

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

+1, looks good to me

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'checkbox-touch/build-me'
--- checkbox-touch/build-me 2015-10-15 09:54:02 +0000
+++ checkbox-touch/build-me 2015-11-25 11:37:27 +0000
@@ -1,5 +1,6 @@
1#!/usr/bin/env python31#!/usr/bin/env python3
2import argparse2import argparse
3from contextlib import contextmanager
3from distutils.dir_util import copy_tree4from distutils.dir_util import copy_tree
4from datetime import datetime5from datetime import datetime
5import json6import json
@@ -9,6 +10,9 @@
9import sys10import sys
10import textwrap11import textwrap
1112
13from confinement.generate import generate_confinement
14from py.embedded_providers import EmbeddedProvider1PlugInCollection
15
12# DEFAULT_PROVIDERS is a list of providers directory names as listed in16# DEFAULT_PROVIDERS is a list of providers directory names as listed in
13# ../providers. NOTE: those are directory names, not provider names as reported17# ../providers. NOTE: those are directory names, not provider names as reported
14# by manage.py info18# by manage.py info
@@ -19,6 +23,24 @@
19]23]
2024
2125
26@contextmanager
27def chdir(path):
28 previous_path = os.getcwd()
29 os.chdir(path)
30 yield
31 os.chdir(previous_path)
32
33
34def get_confined_jobs(path):
35 collection = EmbeddedProvider1PlugInCollection(path)
36 # this should be run within provider's directory, so there should be
37 # only one provider loaded
38 provider = collection.get_all_plugin_objects()[0]
39 for job in provider.job_list:
40 if job.plugin == 'qml' and 'confined' in job.get_flag_set():
41 yield job
42
43
22def check_libs_present():44def check_libs_present():
23 """45 """
24 Check if paths listed in NECESSARY_PATHS are present.46 Check if paths listed in NECESSARY_PATHS are present.
@@ -117,6 +139,16 @@
117 if not validate_providers():139 if not validate_providers():
118 sys.exit('Provider validation failed.')140 sys.exit('Provider validation failed.')
119141
142 current_manifest = json.loads(open('manifest.json', 'rt').read())
143 hooks = {
144 'checkbox-touch': current_manifest['hooks']['checkbox-touch']
145 }
146 for hook in build_confinement(current_manifest['version']):
147 hooks.update(hook)
148 new_manifest = current_manifest.copy()
149 new_manifest['hooks'] = hooks
150 with open('manifest.json', 'wt') as f:
151 f.write(json.dumps(new_manifest, sort_keys=True, indent=4))
120 build_i18n()152 build_i18n()
121153
122 generate_desktop_file()154 generate_desktop_file()
@@ -159,6 +191,21 @@
159 return providers_valid191 return providers_valid
160192
161193
194def build_confinement(checkbox_version):
195 print("Generating confinement")
196 checkbox_name = "com.ubuntu.checkbox_checkbox-touch_" + checkbox_version
197 new_hooks = []
198 for provider_dir in os.listdir('providers'):
199 with chdir(os.path.join('providers', provider_dir)):
200 for job in get_confined_jobs('.'):
201 print(" job: {}".format(job.id))
202 qml_file = os.path.relpath(
203 job.qml_file, 'data')
204 new_hooks.append(generate_confinement(
205 provider_dir, job.partial_id, checkbox_name, qml_file))
206 return new_hooks
207
208
162def build_i18n():209def build_i18n():
163 print("Building i18n")210 print("Building i18n")
164 for provider_dir in os.listdir('providers'):211 for provider_dir in os.listdir('providers'):
165212
=== modified file 'checkbox-touch/checkbox-touch.qml'
--- checkbox-touch/checkbox-touch.qml 2015-11-18 09:00:54 +0000
+++ checkbox-touch/checkbox-touch.qml 2015-11-25 11:37:27 +0000
@@ -658,7 +658,7 @@
658 }658 }
659 function performConfinedQmlTest(test) {659 function performConfinedQmlTest(test) {
660 runTestActivity(test, function(test) {660 runTestActivity(test, function(test) {
661 var qmlNativePage = createPage("components/QmlConfinedPage.qml");661 var qmlNativePage = createPage("components/QmlConfinedPage.qml", test);
662 qmlNativePage.applicationVersion = app.applicationVersion;662 qmlNativePage.applicationVersion = app.applicationVersion;
663 qmlNativePage.testDone.connect(completeTest);663 qmlNativePage.testDone.connect(completeTest);
664 pageStack.push(qmlNativePage);664 pageStack.push(qmlNativePage);
665665
=== modified file 'checkbox-touch/components/CheckboxTouchApplication.qml'
--- checkbox-touch/components/CheckboxTouchApplication.qml 2015-10-15 22:31:52 +0000
+++ checkbox-touch/components/CheckboxTouchApplication.qml 2015-11-25 11:37:27 +0000
@@ -169,6 +169,12 @@
169 continuation_error(error);169 continuation_error(error);
170 });170 });
171 }171 }
172 function dropPermissions(appId, services, continuation, continuation_error) {
173 request("drop_permissions", [appId, services], continuation, function(error) {
174 console.error("Unable to remove permissions");
175 if (continuation_error) continuation_error(error);
176 });
177 }
172178
173 function rememberPassword(password, continuation) {179 function rememberPassword(password, continuation) {
174 // using low-level py.call() to 'silently' pass password string through pyotherside180 // using low-level py.call() to 'silently' pass password string through pyotherside
175181
=== modified file 'checkbox-touch/components/QmlConfinedPage.qml'
--- checkbox-touch/components/QmlConfinedPage.qml 2015-11-17 14:38:41 +0000
+++ checkbox-touch/components/QmlConfinedPage.qml 2015-11-25 11:37:27 +0000
@@ -107,11 +107,35 @@
107 Layout.fillWidth: true107 Layout.fillWidth: true
108 text: i18n.tr("Start the test")108 text: i18n.tr("Start the test")
109 onClicked: {109 onClicked: {
110 busyIndicatorGroup.visible = true;110 var appName = "com.ubuntu.checkbox_" + test["partial_id"];
111 var appName = "com.ubuntu.checkbox_" + test["partial_id"] + "_" + applicationVersion + ".desktop";111 // load the test qml file to check which permissions should be cleared
112 console.log("Launching " + appName);112 var testItemComponent = Qt.createComponent(Qt.resolvedUrl(test['qml_file']));
113 Qt.openUrlExternally("application:///" + appName);113 if (testItemComponent.status == Component.Error) {
114 console.error("Error creating testItemComponent. Possible cause: Problem with job's qml file. Error:", testItemComponent.errorString());
115 test['outcome'] = 'fail';
116 testDone(test);
117 return;
118 }
119 var testItem = testItemComponent.createObject(dummyContainer, {"testingShell": testingShell});
120 var clearedPermissions = testItem.clearedPermissions;
121 testItem.destroy();
122 var runConfinedTestApp = function() {
123 busyIndicatorGroup.visible = true;
124 Qt.openUrlExternally("application:///" + appName + "_" + applicationVersion+ ".desktop");
125 }
126 if (clearedPermissions) {
127 app.dropPermissions(appName, clearedPermissions, function() {
128 runConfinedTestApp();
129 });
130 } else {
131 runConfinedTestApp();
132 }
133
114 }134 }
115 }135 }
136 Item {
137 id: dummyContainer
138 visible: false
139 }
116 }140 }
117}141}
118142
=== renamed file 'checkbox-touch/confinement/generate-confinement.py' => 'checkbox-touch/confinement/generate.py'
--- checkbox-touch/confinement/generate-confinement.py 2015-07-23 10:54:18 +0000
+++ checkbox-touch/confinement/generate.py 2015-11-25 11:37:27 +0000
@@ -17,6 +17,7 @@
17# You should have received a copy of the GNU General Public License17# You should have received a copy of the GNU General Public License
18# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.18# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
19import argparse19import argparse
20import json
20import os21import os
21import string22import string
22import sys23import sys
@@ -49,15 +50,9 @@
49X-Ubuntu-Touch=true50X-Ubuntu-Touch=true
50"""51"""
5152
52HOOK = """
53"${partial_id}": {
54 "apparmor": "providers/${provider_name}/data/confined/${partial_id}.apparmor",
55 "desktop": "providers/${provider_name}/data/confined/${partial_id}.desktop",
56 "content-hub": "providers/${provider_name}/data/confined/${partial_id}-ch.json"
57}
58"""
5953
60def generate_confinement(provider_name, partial_id, full_checkbox_name, qml_file):54def generate_confinement(provider_name, partial_id, full_checkbox_name,
55 qml_file):
61 # generate content-hub file56 # generate content-hub file
62 target_dir = os.path.join('data', 'confined')57 target_dir = os.path.join('data', 'confined')
63 if not os.path.exists(target_dir):58 if not os.path.exists(target_dir):
@@ -72,17 +67,24 @@
72 with open(apparmor_path, "wt") as f:67 with open(apparmor_path, "wt") as f:
73 f.write(APPARMOR)68 f.write(APPARMOR)
7469
75
76 # generate desktop file70 # generate desktop file
77 desktop_path = os.path.join(target_dir, partial_id + '.desktop')71 desktop_path = os.path.join(target_dir, partial_id + '.desktop')
78 template = string.Template(DESKTOP)72 template = string.Template(DESKTOP)
79 with open(desktop_path, "wt") as f:73 with open(desktop_path, "wt") as f:
80 f.write(template.substitute(partial_id=partial_id, provider_name=provider_name, full_checkbox_name=full_checkbox_name, qml_file=qml_file))74 f.write(template.substitute(
75 partial_id=partial_id, provider_name=provider_name,
76 full_checkbox_name=full_checkbox_name, qml_file=qml_file))
8177
82def generate_hook(provider_name, partial_id):78 base = 'providers/{provider_name}/data/confined/{partial_id}'.format(
83 return string.Template(HOOK).substitute(
84 provider_name=provider_name, partial_id=partial_id)79 provider_name=provider_name, partial_id=partial_id)
8580 hook = {
81 partial_id: {
82 'apparmor': base + '.apparmor',
83 'desktop': base + '.desktop',
84 'content-hub': base + '-ch.json',
85 }
86 }
87 return hook
8688
8789
88def main():90def main():
@@ -91,7 +93,8 @@
91 parser.add_argument('--checkbox_version', action='store', type=str)93 parser.add_argument('--checkbox_version', action='store', type=str)
92 parser.add_argument('job_ids', nargs='+')94 parser.add_argument('job_ids', nargs='+')
93 args = parser.parse_args()95 args = parser.parse_args()
94 checkbox_name = "com.ubuntu.checkbox_checkbox-touch_" + args.checkbox_version96 checkbox_name = ("com.ubuntu.checkbox_checkbox-touch_" +
97 args.checkbox_version)
9598
96 # check if current dir looks like a provider - very dumb heuristic99 # check if current dir looks like a provider - very dumb heuristic
97 if not os.path.exists('manage.py'):100 if not os.path.exists('manage.py'):
@@ -100,8 +103,9 @@
100103
101 hooks = ''104 hooks = ''
102 for job in args.job_ids:105 for job in args.job_ids:
103 generate_confinement(provider_name, job, checkbox_name, job + '.qml')106 hook = generate_confinement(
104 hooks += generate_hook(provider_name, job)107 provider_name, job, checkbox_name, job + '.qml')
108 hooks += json.dumps(hook, sort_keys=True, indent=4)[1:-1]
105109
106 print("Add following hooks to your checkbox-touch.manifest:")110 print("Add following hooks to your checkbox-touch.manifest:")
107 print(hooks)111 print(hooks)
108112
=== modified file 'checkbox-touch/manifest.json'
--- checkbox-touch/manifest.json 2015-11-16 09:17:41 +0000
+++ checkbox-touch/manifest.json 2015-11-25 11:37:27 +0000
@@ -11,9 +11,9 @@
11 "maintainer": "Zygmunt Krynicki <zkrynicki@ubuntu.com>",11 "maintainer": "Zygmunt Krynicki <zkrynicki@ubuntu.com>",
12 "name": "com.ubuntu.checkbox",12 "name": "com.ubuntu.checkbox",
13 "title": "Checkbox",13 "title": "Checkbox",
14 "version": "1.3.dev0",14 "version": "1.3.dev",
15 "x-source": {15 "x-source": {
16 "vcs-bzr": "lp:checkbox",16 "vcs-bzr": "lp:checkbox",
17 "vcs-bzr-revno": "checkbox-touch-v1.3.dev0"17 "vcs-bzr-revno": "checkbox-touch-v1.3.dev"
18 }18 }
19}19}
2020
=== modified file 'checkbox-touch/py/checkbox_touch.py'
--- checkbox-touch/py/checkbox_touch.py 2015-11-16 10:20:39 +0000
+++ checkbox-touch/py/checkbox_touch.py 2015-11-25 11:37:27 +0000
@@ -36,6 +36,7 @@
36import logging36import logging
37import os37import os
38import pyotherside38import pyotherside
39import sqlite3
39import re40import re
40import time41import time
41import traceback42import traceback
@@ -133,7 +134,7 @@
133 response data to alter the user interface.134 response data to alter the user interface.
134 """135 """
135136
136 __version__ = (1, 2, 1, 'final', 0)137 __version__ = (1, 3, 0, 'dev', 0)
137138
138 def __init__(self):139 def __init__(self):
139 if plainbox.__version__ < (0, 22):140 if plainbox.__version__ < (0, 22):
@@ -459,6 +460,28 @@
459 return self.assistant.export_to_transport(460 return self.assistant.export_to_transport(
460 '2013.com.canonical.plainbox::hexr', transport)461 '2013.com.canonical.plainbox::hexr', transport)
461462
463 @view
464 def drop_permissions(self, app_id, services):
465 # TODO: use XDG once available
466 trust_dbs = {
467 'camera': '~/.local/share/CameraService/trust.db',
468 'audio': '~/.local/share/PulseAudio/trust.db',
469 'location': '~/.local/share/UbuntuLocationServices/trust.db',
470 }
471 sql = 'delete from requests where ApplicationId = (?);'
472
473 for service in services:
474 conn = None
475 try:
476 conn = sqlite3.connect(
477 os.path.expanduser(trust_dbs[service]),
478 isolation_level='EXCLUSIVE')
479 conn.execute(sql, (app_id,))
480 conn.commit()
481 finally:
482 if conn:
483 conn.close()
484
462 def _get_user_directory_documents(self):485 def _get_user_directory_documents(self):
463 xdg_config_home = os.environ.get('XDG_CONFIG_HOME') or \486 xdg_config_home = os.environ.get('XDG_CONFIG_HOME') or \
464 os.path.expanduser('~/.config')487 os.path.expanduser('~/.config')
465488
=== modified file 'plainbox/plainbox/data/plainbox-qml-modules/Plainbox/QmlJob.qml'
--- plainbox/plainbox/data/plainbox-qml-modules/Plainbox/QmlJob.qml 2015-07-07 08:32:21 +0000
+++ plainbox/plainbox/data/plainbox-qml-modules/Plainbox/QmlJob.qml 2015-11-25 11:37:27 +0000
@@ -24,4 +24,5 @@
24Item {24Item {
25 signal testDone(var testResult)25 signal testDone(var testResult)
26 property var testingShell;26 property var testingShell;
27 property var clearedPermissions: [];
27}28}

Subscribers

People subscribed via source and target branches