From 8b1685b5b726d98d50e83acf04279d4a9ccb2eeb Mon Sep 17 00:00:00 2001 From: José Bollo Date: Tue, 19 Mar 2019 23:21:35 +0100 Subject: Add ability to manage all widget/applications For system uses -like automatic testing-, it is needed to include tha ability to list ALL installed widgets and ALL running instance of installed widgets. This change adds the option -a or --all to the commands 'list' and 'runners' for the purpose of listing any installed widgets, even those requiring to be hidden. Example: afm-util ps -a Bug-AGL: SPEC-2272 Bug-AGL: SPEC-1850 Change-Id: I216ec9c63efea1b3af58e1d2d7723d986e04551e Signed-off-by: Jose Bollo --- conf/unit/afm-unit-debug.conf.in | 1 + conf/unit/afm-unit.conf.in | 1 + conf/unit/generate-unit-conf/service.inc | 1 + scripts/afm-util.in | 13 ++- src/afm-binding.c | 25 +++++- src/afm-udb.c | 136 ++++++++++++++++++------------- src/afm-udb.h | 4 +- src/afm-urun.c | 6 +- src/afm-urun.h | 2 +- 9 files changed, 122 insertions(+), 67 deletions(-) diff --git a/conf/unit/afm-unit-debug.conf.in b/conf/unit/afm-unit-debug.conf.in index 01d3c2e..eb26540 100644 --- a/conf/unit/afm-unit-debug.conf.in +++ b/conf/unit/afm-unit-debug.conf.in @@ -104,6 +104,7 @@ X-AFM--content={{content.src}} X-AFM--type={{content.type}} X-AFM--wgtdir={{:#metadata.install-dir}} X-AFM--workdir=/home/%i/app-data/{{:id}} +X-AFM--visibility={{#required-permission.urn:AGL:permission::public:hidden}}hidden{{/required-permission.urn:AGL:permission::public:hidden}}{{^required-permission.urn:AGL:permission::public:hidden}}visible{{/required-permission.urn:AGL:permission::public:hidden}} %nl Requires=afm-user-session@%i.target After=user@%i.service diff --git a/conf/unit/afm-unit.conf.in b/conf/unit/afm-unit.conf.in index 74c57ea..46c78c7 100644 --- a/conf/unit/afm-unit.conf.in +++ b/conf/unit/afm-unit.conf.in @@ -104,6 +104,7 @@ X-AFM--content={{content.src}} X-AFM--type={{content.type}} X-AFM--wgtdir={{:#metadata.install-dir}} X-AFM--workdir=/home/%i/app-data/{{:id}} +X-AFM--visibility={{#required-permission.urn:AGL:permission::public:hidden}}hidden{{/required-permission.urn:AGL:permission::public:hidden}}{{^required-permission.urn:AGL:permission::public:hidden}}visible{{/required-permission.urn:AGL:permission::public:hidden}} %nl Requires=afm-user-session@%i.target After=user@%i.service diff --git a/conf/unit/generate-unit-conf/service.inc b/conf/unit/generate-unit-conf/service.inc index 1df4210..671d1d5 100644 --- a/conf/unit/generate-unit-conf/service.inc +++ b/conf/unit/generate-unit-conf/service.inc @@ -30,6 +30,7 @@ X-AFM--content={{content.src}} X-AFM--type={{content.type}} X-AFM--wgtdir={{:#metadata.install-dir}} X-AFM--workdir=APP_DATA_DIR/{{:id}} +X-AFM--visibility=ON_PERM(`:public:hidden', `hidden', `visible') %nl Requires=afm-user-session@%i.target diff --git a/scripts/afm-util.in b/scripts/afm-util.in index 3f47d97..978f000 100755 --- a/scripts/afm-util.in +++ b/scripts/afm-util.in @@ -5,10 +5,17 @@ send() { awk '$1=="ON-REPLY" && $3!="success"{$1="ERROR:";$2="";print > "/dev/stderr";exit 1;}NR>1' } +getall() { + case "$1" in + -a|--all) echo -n '{"all":true}';; + *) echo -n true;; + esac +} + case "$1" in list|runnables) - send runnables true + send runnables $(getall $2) ;; add|install) @@ -29,7 +36,7 @@ case "$1" in ;; ps|runners) - send runners true + send runners $(getall $2) ;; run|start) @@ -75,6 +82,7 @@ The commands are: list runnables list the runnable widgets installed + option -a or --all for all instances add wgt install wgt install the wgt file @@ -87,6 +95,7 @@ The commands are: ps runners list the running instance + option -a or --all for all instances run id start id start an instance of the widget of id diff --git a/src/afm-binding.c b/src/afm-binding.c index f4bba8a..34880fc 100644 --- a/src/afm-binding.c +++ b/src/afm-binding.c @@ -41,6 +41,7 @@ * constant strings */ static const char _added_[] = "added"; +static const char _all_[] = "all"; static const char _a_l_c_[] = "application-list-changed"; static const char _bad_request_[] = "bad-request"; static const char _cannot_start_[] = "cannot-start"; @@ -226,6 +227,18 @@ static const char *get_lang(afb_req_t req) return lang; } +/* + * Retrieve whether all is required from 'req'. + */ +static int get_all(afb_req_t req) +{ + struct json_object *val; + + /* get the optional language */ + return json_object_object_get_ex(afb_req_json(req), _all_, &val) + && json_object_get_boolean(val); +} + /* * retrieves the 'appid' in parameters received with the @@ -328,14 +341,18 @@ static void reply_status(afb_req_t req, int status) */ static void runnables(afb_req_t req) { + int all; const char *lang; struct json_object *resp; /* get the language */ lang = get_lang(req); + /* get the all */ + all = get_all(req); + /* get the details */ - resp = afm_udb_applications_public(afudb, afb_req_get_uid(req), lang); + resp = afm_udb_applications_public(afudb, all, afb_req_get_uid(req), lang); afb_req_success(req, resp, NULL); } @@ -473,8 +490,10 @@ static void terminate(afb_req_t req) */ static void runners(afb_req_t req) { + int all; struct json_object *resp; - resp = afm_urun_list(afudb, afb_req_get_uid(req)); + all = get_all(req); + resp = afm_urun_list(afudb, all, afb_req_get_uid(req)); afb_req_success(req, resp, NULL); } @@ -585,7 +604,7 @@ static int init(afb_api_t api) json_true = json_object_new_boolean(1); /* init database */ - afudb = afm_udb_create(1, 0, "afm-appli-"); + afudb = afm_udb_create(1, 0, "afm-"); if (!afudb) { ERROR("afm_udb_create failed"); return -1; diff --git a/src/afm-udb.c b/src/afm-udb.c index 7f4a16e..6357a2d 100644 --- a/src/afm-udb.c +++ b/src/afm-udb.c @@ -42,6 +42,8 @@ static const char key_unit_scope[] = "-unit-scope"; static const char scope_user[] = "user"; static const char scope_system[] = "system"; static const char key_id[] = "id"; +static const char key_visibility[] = "visibility"; +static const char value_visible[] = "visible"; #define x_afm_prefix_length (sizeof x_afm_prefix - 1) #define service_extension_length (sizeof service_extension - 1) @@ -51,10 +53,11 @@ static const char key_id[] = "id"; * for several accesses. */ struct afm_apps { - struct json_object *prvarr; /* array of the private data of apps */ - struct json_object *pubarr; /* array of the public data of apps */ - struct json_object *pubobj; /* hash of application's publics */ - struct json_object *prvobj; /* hash of application's privates */ + struct { + struct json_object *visibles; /* array of the private data of visible apps */ + struct json_object *all; /* array of the private data of all apps */ + struct json_object *byname; /* hash of application's privates */ + } privates, publics; }; /* @@ -83,15 +86,39 @@ struct afm_updt { */ static char *default_lang; +/* + * initilize object 'apps'. + * returns 1 if okay or 0 on case of memory depletion + */ +static int apps_init(struct afm_apps *apps) +{ + apps->publics.all = json_object_new_array(); + apps->publics.visibles = json_object_new_array(); + apps->publics.byname = json_object_new_object(); + + apps->privates.all = json_object_new_array(); + apps->privates.visibles = json_object_new_array(); + apps->privates.byname = json_object_new_object(); + + return apps->publics.all + && apps->publics.visibles + && apps->publics.byname + && apps->privates.all + && apps->privates.visibles + && apps->privates.byname; +} + /* * Release the data of the afm_apps object 'apps'. */ static void apps_put(struct afm_apps *apps) { - json_object_put(apps->prvarr); - json_object_put(apps->pubarr); - json_object_put(apps->pubobj); - json_object_put(apps->prvobj); + json_object_put(apps->publics.all); + json_object_put(apps->publics.visibles); + json_object_put(apps->publics.byname); + json_object_put(apps->privates.all); + json_object_put(apps->privates.visibles); + json_object_put(apps->privates.byname); } /* @@ -161,8 +188,10 @@ static int add_field( /* add the value */ if (name[0] == '-') { + /* private value */ append_field(priv, &name[1], v); } else { + /* public value */ append_field(priv, name, json_object_get(v)); append_field(pub, name, v); } @@ -236,7 +265,7 @@ static int addunit( size_t length ) { - struct json_object *priv, *pub, *id; + struct json_object *priv, *pub, *id, *visi; const char *strid; size_t len; @@ -270,11 +299,19 @@ static int addunit( /* record the application structure */ json_object_get(pub); - json_object_array_add(apps->pubarr, pub); - json_object_object_add(apps->pubobj, strid, pub); + json_object_array_add(apps->publics.all, pub); + json_object_object_add(apps->publics.byname, strid, pub); json_object_get(priv); - json_object_array_add(apps->prvarr, priv); - json_object_object_add(apps->prvobj, strid, priv); + json_object_array_add(apps->privates.all, priv); + json_object_object_add(apps->privates.byname, strid, priv); + + /* handle visibility */ + if (json_object_object_get_ex(priv, key_visibility, &visi) + && !strcasecmp(json_object_get_string(visi), value_visible)) { + json_object_array_add(apps->publics.visibles, json_object_get(pub)); + json_object_array_add(apps->privates.visibles, json_object_get(priv)); + } + return 0; error: @@ -406,10 +443,7 @@ struct afm_udb *afm_udb_create(int sys, int usr, const char *prefix) errno = ENOMEM; else { afudb->refcount = 1; - afudb->applications.prvarr = NULL; - afudb->applications.pubarr = NULL; - afudb->applications.pubobj = NULL; - afudb->applications.prvobj = NULL; + memset(&afudb->applications, 0, sizeof afudb->applications); afudb->system = sys; afudb->user = usr; afudb->prefixlen = length; @@ -456,43 +490,33 @@ int afm_udb_update(struct afm_udb *afudb) { struct afm_updt updt; struct afm_apps tmp; + int result; /* lock the db */ afm_udb_addref(afudb); updt.afudb = afudb; - /* create the result */ - updt.applications.prvarr = json_object_new_array(); - updt.applications.pubarr = json_object_new_array(); - updt.applications.pubobj = json_object_new_object(); - updt.applications.prvobj = json_object_new_object(); - if (updt.applications.pubarr == NULL - || updt.applications.prvarr == NULL - || updt.applications.pubobj == NULL - || updt.applications.prvobj == NULL) { - errno = ENOMEM; - goto error; + /* create the apps */ + if (!apps_init(&updt.applications)) + result = -1; + else { + /* scan the units */ + if (afudb->user && systemd_unit_list(1, update_cb, &updt) < 0) + result = -1; + else if (afudb->system && systemd_unit_list(0, update_cb, &updt) < 0) + result = -1; + else { + /* commit the result */ + tmp = afudb->applications; + afudb->applications = updt.applications; + updt.applications = tmp; + result = 0; + } + apps_put(&updt.applications); } - - /* scan the units */ - if (afudb->user) - if (systemd_unit_list(1, update_cb, &updt) < 0) - goto error; - if (afudb->system) - if (systemd_unit_list(0, update_cb, &updt) < 0) - goto error; - - /* commit the result */ - tmp = afudb->applications; - afudb->applications = updt.applications; - apps_put(&tmp); + /* unlock the db and return status */ afm_udb_unref(afudb); - return 0; - -error: - apps_put(&updt.applications); - afm_udb_unref(afudb); - return -1; + return result; } /* @@ -511,9 +535,9 @@ void afm_udb_set_default_lang(const char *lang) * 'json_object_put'. * Returns NULL in case of error. */ -struct json_object *afm_udb_applications_private(struct afm_udb *afudb, int uid) +struct json_object *afm_udb_applications_private(struct afm_udb *afudb, int all, int uid) { - return json_object_get(afudb->applications.prvarr); + return json_object_get(all ? afudb->applications.privates.all : afudb->applications.privates.visibles); } /* @@ -522,9 +546,9 @@ struct json_object *afm_udb_applications_private(struct afm_udb *afudb, int uid) * 'json_object_put'. * Returns NULL in case of error. */ -struct json_object *afm_udb_applications_public(struct afm_udb *afudb, int uid, const char *lang) +struct json_object *afm_udb_applications_public(struct afm_udb *afudb, int all, int uid, const char *lang) { - return json_object_get(afudb->applications.pubarr); + return json_object_get(all ? afudb->applications.publics.all : afudb->applications.publics.visibles); } /* @@ -556,7 +580,7 @@ static struct json_object *get_no_case(struct json_object *object, const char *i */ struct json_object *afm_udb_get_application_private(struct afm_udb *afudb, const char *id, int uid) { - return get_no_case(afudb->applications.prvobj, id, uid, NULL); + return get_no_case(afudb->applications.privates.byname, id, uid, NULL); } /* @@ -567,7 +591,7 @@ struct json_object *afm_udb_get_application_private(struct afm_udb *afudb, const struct json_object *afm_udb_get_application_public(struct afm_udb *afudb, const char *id, int uid, const char *lang) { - return get_no_case(afudb->applications.pubobj, id, uid, lang); + return get_no_case(afudb->applications.publics.byname, id, uid, lang); } @@ -577,9 +601,9 @@ struct json_object *afm_udb_get_application_public(struct afm_udb *afudb, int main() { struct afm_udb *afudb = afm_udb_create(1, 1, NULL); -printf("array = %s\n", json_object_to_json_string_ext(afudb->applications.pubarr, 3)); -printf("pubobj = %s\n", json_object_to_json_string_ext(afudb->applications.pubobj, 3)); -printf("prvobj = %s\n", json_object_to_json_string_ext(afudb->applications.prvobj, 3)); +printf("publics.all = %s\n", json_object_to_json_string_ext(afudb->applications.publics.all, 3)); +printf("publics.byname = %s\n", json_object_to_json_string_ext(afudb->applications.publics.byname, 3)); +printf("privates.byname = %s\n", json_object_to_json_string_ext(afudb->applications.privates.byname, 3)); return 0; } #endif diff --git a/src/afm-udb.h b/src/afm-udb.h index 810c295..90775fe 100644 --- a/src/afm-udb.h +++ b/src/afm-udb.h @@ -24,8 +24,8 @@ extern void afm_udb_addref(struct afm_udb *afdb); extern void afm_udb_unref(struct afm_udb *afdb); extern int afm_udb_update(struct afm_udb *afdb); extern void afm_udb_set_default_lang(const char *lang); -extern struct json_object *afm_udb_applications_private(struct afm_udb *afdb, int uid); +extern struct json_object *afm_udb_applications_private(struct afm_udb *afdb, int all, int uid); extern struct json_object *afm_udb_get_application_private(struct afm_udb *afdb, const char *id, int uid); -extern struct json_object *afm_udb_applications_public(struct afm_udb *afdb, int uid, const char *lang); +extern struct json_object *afm_udb_applications_public(struct afm_udb *afdb, int all, int uid, const char *lang); extern struct json_object *afm_udb_get_application_public(struct afm_udb *afdb, const char *id, int uid, const char *lang); diff --git a/src/afm-urun.c b/src/afm-urun.c index 882d44c..7d82cdd 100644 --- a/src/afm-urun.c +++ b/src/afm-urun.c @@ -326,7 +326,7 @@ int afm_urun_resume(int runid, int uid) * * Returns the list or NULL in case of error. */ -struct json_object *afm_urun_list(struct afm_udb *db, int uid) +struct json_object *afm_urun_list(struct afm_udb *db, int all, int uid) { int i, n, isuser, pid; const char *udpath; @@ -342,7 +342,7 @@ struct json_object *afm_urun_list(struct afm_udb *db, int uid) if (result == NULL) goto error; - apps = afm_udb_applications_private(db, uid); + apps = afm_udb_applications_private(db, all, uid); n = json_object_array_length(apps); for (i = 0 ; i < n ; i++) { appli = json_object_array_get_idx(apps, i); @@ -393,7 +393,7 @@ struct json_object *afm_urun_state(struct afm_udb *db, int runid, int uid) WARNING("searched runid %d not found", runid); } else { /* search in the base */ - apps = afm_udb_applications_private(db, uid); + apps = afm_udb_applications_private(db, 1, uid); n = json_object_array_length(apps); for (i = 0 ; i < n ; i++) { appli = json_object_array_get_idx(apps, i); diff --git a/src/afm-urun.h b/src/afm-urun.h index e2a15ab..dc9731f 100644 --- a/src/afm-urun.h +++ b/src/afm-urun.h @@ -23,7 +23,7 @@ extern int afm_urun_once(struct json_object *appli, int uid); extern int afm_urun_terminate(int runid, int uid); extern int afm_urun_pause(int runid, int uid); extern int afm_urun_resume(int runid, int uid); -extern struct json_object *afm_urun_list(struct afm_udb *db, int uid); +extern struct json_object *afm_urun_list(struct afm_udb *db, int all, int uid); extern struct json_object *afm_urun_state(struct afm_udb *db, int runid, int uid); extern int afm_urun_search_runid(struct afm_udb *db, const char *id, int uid); -- cgit 1.2.3-korg