feat(settings): settings app: apps list + per-capability allow/revoke, about (who/role), sign out; system-only caps permissions/session (install refused); pm MANAGE_BADGE copy (list/apps/allow/revoke only), APPS op; init WHO + session pass-on; factory decisions seeded for new system apps; k-ui list_item/toggle, screens/back/scroll
This commit is contained in:
@@ -100,6 +100,15 @@ impl Apps {
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Every installed app, for a program to read (see `entries`), into
|
||||
/// `out`; how much.
|
||||
pub fn apps(&self, out: &mut [u8]) -> Result<usize> {
|
||||
let (len, _) = self.with_page(wire::APPS, 0)?;
|
||||
let len = len.min(out.len()).min(PAGE_SIZE);
|
||||
self.page.copy_to(ByteOffset::ZERO, &mut out[..len]);
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Takes the capability with catalog index `capability` away from app
|
||||
/// `id` (stopping it if it runs with it).
|
||||
pub fn revoke(&self, id: &str, capability: usize) -> Result<()> {
|
||||
@@ -114,3 +123,37 @@ impl Apps {
|
||||
self.with_page(wire::ALLOW, capability).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// One installed app, as `Apps::apps` lists it.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct AppEntry<'a> {
|
||||
pub id: &'a str,
|
||||
pub name: &'a str,
|
||||
/// Capability bits (`manifest::Capabilities`).
|
||||
pub required: u32,
|
||||
pub optional: u32,
|
||||
pub granted: u32,
|
||||
}
|
||||
|
||||
/// The apps in a listing; a line that does not parse is skipped.
|
||||
pub fn entries(text: &str) -> impl Iterator<Item = AppEntry<'_>> {
|
||||
text.lines().filter_map(|line| {
|
||||
let mut f = line.split('\t');
|
||||
let (id, name) = (f.next()?, f.next()?);
|
||||
let mut bits = || f.next()?.parse().ok();
|
||||
Some(AppEntry { id, name, required: bits()?, optional: bits()?, granted: bits()? })
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn a_listing_parses_and_bad_lines_are_skipped() {
|
||||
let text = "kos.snake\tSnake\t1\t0\t1\nnonsense\nkos.notes\tNotes\t0\t3\t2\n";
|
||||
let all: alloc::vec::Vec<_> = entries(text).collect();
|
||||
assert_eq!(all.len(), 2);
|
||||
assert_eq!(all[1], AppEntry { id: "kos.notes", name: "Notes", required: 0, optional: 3, granted: 2 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ pub mod input;
|
||||
pub mod io;
|
||||
mod rt;
|
||||
pub mod spawn;
|
||||
pub mod session;
|
||||
pub mod start;
|
||||
pub mod terminal;
|
||||
pub mod syscall;
|
||||
|
||||
33
crates/libkos/src/session.rs
Normal file
33
crates/libkos/src/session.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
//! The session capability's client (`types::spawn::WHO`, `SIGN_OUT`): who
|
||||
//! is signed in, and signing out. Init answers it.
|
||||
|
||||
use crate::syscall;
|
||||
use types::bounded::CapSlot;
|
||||
use types::spawn::{SIGN_OUT, WHO, role};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Role {
|
||||
Owner,
|
||||
Standard,
|
||||
Guest,
|
||||
}
|
||||
|
||||
/// Who is signed in: their name (into `name`, how long) and role.
|
||||
pub fn who(session: CapSlot, name: &mut [u8; types::name::BYTES]) -> Option<(usize, Role)> {
|
||||
let [r, a, b, c] = syscall::request(session, [WHO, 0, 0, 0]).ok()?;
|
||||
let role = match r {
|
||||
role::OWNER => Role::Owner,
|
||||
role::STANDARD => Role::Standard,
|
||||
role::GUEST => Role::Guest,
|
||||
_ => return None,
|
||||
};
|
||||
let (bytes, len) = types::name::unpack([a, b, c]);
|
||||
*name = bytes;
|
||||
Some((len, role))
|
||||
}
|
||||
|
||||
/// Signs the user out: init stops everything the session runs, this
|
||||
/// program included, and the lock screen comes back.
|
||||
pub fn sign_out(session: CapSlot) -> bool {
|
||||
syscall::send_msg(session, [SIGN_OUT, 0, 0, 0], None).is_ok()
|
||||
}
|
||||
@@ -44,6 +44,18 @@ pub fn data() -> Option<CapSlot> {
|
||||
StartArg::decode(arg()).data
|
||||
}
|
||||
|
||||
/// The permission manager's management interface, if this app was granted
|
||||
/// `permissions`.
|
||||
pub fn permissions() -> Option<CapSlot> {
|
||||
StartArg::decode(arg()).permissions
|
||||
}
|
||||
|
||||
/// The session (who is signed in, signing out), if this app was granted
|
||||
/// `session`.
|
||||
pub fn session() -> Option<CapSlot> {
|
||||
StartArg::decode(arg()).session
|
||||
}
|
||||
|
||||
/// The display server endpoint this process was given, if any.
|
||||
pub fn display() -> Option<CapSlot> {
|
||||
StartArg::decode(arg()).display
|
||||
|
||||
Reference in New Issue
Block a user