[fractal/fractal-next] login: Use SecretService to store previous session



commit abf2361a80893c931705e1976cada751ce1b8e90
Author: Julian Sparber <julian sparber net>
Date:   Wed Mar 24 15:23:29 2021 +0100

    login: Use SecretService to store previous session

 Cargo.lock                                 | 409 +++++++++++++++++++++++++++--
 Cargo.toml                                 |   1 +
 build-aux/org.gnome.FractalNext.Devel.json |   1 +
 src/login.rs                               |  19 +-
 src/main.rs                                |   1 +
 src/meson.build                            |   1 +
 src/secret.rs                              |  69 +++++
 src/session/mod.rs                         |  28 +-
 src/window.rs                              |   6 +
 9 files changed, 508 insertions(+), 27 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 68fe1bf0..69767f8f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -89,6 +89,26 @@ version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002"
 
+[[package]]
+name = "async-io"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "9315f8f07556761c3e48fec2e6b276004acf426e6dc068b2c2251854d65ee0fd"
+dependencies = [
+ "concurrent-queue",
+ "fastrand",
+ "futures-lite",
+ "libc",
+ "log",
+ "nb-connect",
+ "once_cell",
+ "parking",
+ "polling",
+ "vec-arena",
+ "waker-fn",
+ "winapi",
+]
+
 [[package]]
 name = "async-trait"
 version = "0.1.48"
@@ -173,6 +193,22 @@ dependencies = [
  "generic-array",
 ]
 
+[[package]]
+name = "block-modes"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0"
+dependencies = [
+ "block-padding",
+ "cipher",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
+
 [[package]]
 name = "bumpalo"
 version = "3.6.1"
@@ -191,6 +227,12 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
 
+[[package]]
+name = "cache-padded"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
+
 [[package]]
 name = "cairo-rs"
 version = "0.13.0"
@@ -229,6 +271,12 @@ dependencies = [
  "smallvec",
 ]
 
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
@@ -276,6 +324,15 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "concurrent-queue"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
+dependencies = [
+ "cache-padded",
+]
+
 [[package]]
 name = "const_fn"
 version = "0.4.5"
@@ -316,7 +373,7 @@ version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
 ]
 
 [[package]]
@@ -325,7 +382,7 @@ version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "crossbeam-utils",
  "lazy_static",
  "memoffset",
@@ -339,7 +396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
 dependencies = [
  "autocfg",
- "cfg-if",
+ "cfg-if 1.0.0",
  "lazy_static",
 ]
 
@@ -368,10 +425,21 @@ version = "4.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "num_cpus",
 ]
 
+[[package]]
+name = "derivative"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "digest"
 version = "0.9.0"
@@ -399,7 +467,28 @@ version = "0.8.28"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "enumflags2"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "83c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0"
+dependencies = [
+ "enumflags2_derive",
+ "serde",
+]
+
+[[package]]
+name = "enumflags2_derive"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -415,6 +504,15 @@ dependencies = [
  "termcolor",
 ]
 
+[[package]]
+name = "fastrand"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3"
+dependencies = [
+ "instant",
+]
+
 [[package]]
 name = "field-offset"
 version = "0.3.3"
@@ -468,6 +566,7 @@ dependencies = [
  "matrix-sdk",
  "once_cell",
  "pretty_env_logger",
+ "secret-service",
  "serde_json",
  "tokio",
  "url",
@@ -552,6 +651,21 @@ version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
 
+[[package]]
+name = "futures-lite"
+version = "1.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "b4481d0cd0de1d204a4fa55e7d45f07b1d958abcb06714b3446438e2eff695fb"
+dependencies = [
+ "fastrand",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "parking",
+ "pin-project-lite",
+ "waker-fn",
+]
+
 [[package]]
 name = "futures-locks"
 version = "0.6.0"
@@ -693,7 +807,7 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "js-sys",
  "libc",
  "wasi",
@@ -976,6 +1090,16 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "hkdf"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
+dependencies = [
+ "digest",
+ "hmac",
+]
+
 [[package]]
 name = "hmac"
 version = "0.10.1"
@@ -1046,7 +1170,7 @@ dependencies = [
  "httpdate",
  "itoa",
  "pin-project",
- "socket2",
+ "socket2 0.3.19",
  "tokio",
  "tower-service",
  "tracing",
@@ -1093,7 +1217,7 @@ version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "js-sys",
  "time",
  "wasm-bindgen",
@@ -1221,7 +1345,7 @@ version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
 ]
 
 [[package]]
@@ -1394,6 +1518,29 @@ dependencies = [
  "tempfile",
 ]
 
+[[package]]
+name = "nb-connect"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "a19900e7eee95eb2b3c2e26d12a874cc80aaf750e31be6fcbe743ead369fa45d"
+dependencies = [
+ "libc",
+ "socket2 0.4.0",
+]
+
+[[package]]
+name = "nix"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
+dependencies = [
+ "bitflags",
+ "cc",
+ "cfg-if 0.1.10",
+ "libc",
+ "void",
+]
+
 [[package]]
 name = "ntapi"
 version = "0.3.6"
@@ -1403,6 +1550,82 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "num"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
+dependencies = [
+ "num-bigint",
+ "num-complex",
+ "num-integer",
+ "num-iter",
+ "num-rational",
+ "num-traits",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "7d0a3d5e207573f948a9e5376662aa743a2ea13f7c50a554d7af443a73fbfeba"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-complex"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
+dependencies = [
+ "autocfg",
+ "num-bigint",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
+
 [[package]]
 name = "num_cpus"
 version = "1.13.0"
@@ -1483,7 +1706,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577"
 dependencies = [
  "bitflags",
- "cfg-if",
+ "cfg-if 1.0.0",
  "foreign-types",
  "libc",
  "once_cell",
@@ -1532,6 +1755,12 @@ dependencies = [
  "system-deps",
 ]
 
+[[package]]
+name = "parking"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
+
 [[package]]
 name = "parking_lot"
 version = "0.11.1"
@@ -1549,7 +1778,7 @@ version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "instant",
  "libc",
  "redox_syscall",
@@ -1625,6 +1854,19 @@ version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
 
+[[package]]
+name = "polling"
+version = "2.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "4fc12d774e799ee9ebae13f4076ca003b40d18a11ac0f3641e6f899618580b7b"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "log",
+ "wepoll-sys",
+ "winapi",
+]
+
 [[package]]
 name = "poly1305"
 version = "0.6.2"
@@ -2042,12 +2284,38 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "scoped-tls"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
+
 [[package]]
 name = "scopeguard"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
+[[package]]
+name = "secret-service"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "2400fb1bf2a87b303ada204946294f932ade4929477e9e2bf66d7b49a66656ec"
+dependencies = [
+ "aes",
+ "block-modes",
+ "hkdf",
+ "lazy_static",
+ "num",
+ "rand",
+ "serde",
+ "sha2",
+ "zbus",
+ "zbus_macros",
+ "zvariant",
+ "zvariant_derive",
+]
+
 [[package]]
 name = "security-framework"
 version = "2.1.2"
@@ -2141,6 +2409,17 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "serde_repr"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "serde_urlencoded"
 version = "0.7.0"
@@ -2166,7 +2445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de"
 dependencies = [
  "block-buffer",
- "cfg-if",
+ "cfg-if 1.0.0",
  "cpuid-bool 0.1.2",
  "digest",
  "opaque-debug",
@@ -2206,7 +2485,17 @@ version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "socket2"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
+dependencies = [
  "libc",
  "winapi",
 ]
@@ -2340,7 +2629,7 @@ version = "3.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "libc",
  "rand",
  "redox_syscall",
@@ -2502,7 +2791,7 @@ version = "0.1.25"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "pin-project-lite",
  "tracing-attributes",
  "tracing-core",
@@ -2624,6 +2913,12 @@ version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
 
+[[package]]
+name = "vec-arena"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "34b2f665b594b07095e3ac3f718e13c2197143416fae4c5706cffb7b1af8d7f1"
+
 [[package]]
 name = "version-compare"
 version = "0.0.11"
@@ -2636,6 +2931,18 @@ version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
 
+[[package]]
+name = "void"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+
+[[package]]
+name = "waker-fn"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
+
 [[package]]
 name = "want"
 version = "0.3.0"
@@ -2658,7 +2965,7 @@ version = "0.2.72"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "8fe8f61dba8e5d645a4d8132dc7a0a66861ed5e1045d2c0ed940fab33bac0fbe"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "serde",
  "serde_json",
  "wasm-bindgen-macro",
@@ -2685,7 +2992,7 @@ version = "0.4.22"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "73157efb9af26fb564bb59a009afd1c7c334a44db171d280690d0c3faaec3468"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "js-sys",
  "wasm-bindgen",
  "web-sys",
@@ -2730,6 +3037,15 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "wepoll-sys"
+version = "3.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff"
+dependencies = [
+ "cc",
+]
+
 [[package]]
 name = "winapi"
 version = "0.3.9"
@@ -2770,6 +3086,41 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "zbus"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "40b4d4aa39daed4e32aed75f0c37b969184949a0fdfd5f2e1277abfda61f02a8"
+dependencies = [
+ "async-io",
+ "byteorder",
+ "derivative",
+ "enumflags2",
+ "fastrand",
+ "futures",
+ "nb-connect",
+ "nix",
+ "once_cell",
+ "polling",
+ "scoped-tls",
+ "serde",
+ "serde_repr",
+ "zbus_macros",
+ "zvariant",
+]
+
+[[package]]
+name = "zbus_macros"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "87cc141cda72384bef359badf1808e391d3968f9299e8f3c3cbb78dafa1e0930"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "zeroize"
 version = "1.2.0"
@@ -2790,3 +3141,27 @@ dependencies = [
  "syn",
  "synstructure",
 ]
+
+[[package]]
+name = "zvariant"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "678e7262502a135f49b1ece65010526649be7ee68acb80e1fc5377fc71fef878"
+dependencies = [
+ "byteorder",
+ "enumflags2",
+ "serde",
+ "zvariant_derive",
+]
+
+[[package]]
+name = "zvariant_derive"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "27d7c34325a35020b94343389cc9391e0f8ac245cca9155429c4022d93141241"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 3b799dd2..251afda6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,7 @@ once_cell = "1.5"
 serde_json = "1.0"
 tokio = { version = "1.2", features = ["rt", "rt-multi-thread"] }
 url = "2.2"
+secret-service = "2.0"
 
 [dependencies.gtk]
 package = "gtk4"
diff --git a/build-aux/org.gnome.FractalNext.Devel.json b/build-aux/org.gnome.FractalNext.Devel.json
index 14d61dd2..a7ddb14e 100644
--- a/build-aux/org.gnome.FractalNext.Devel.json
+++ b/build-aux/org.gnome.FractalNext.Devel.json
@@ -11,6 +11,7 @@
         "--share=network",
         "--device=dri",
         "--talk-name=org.a11y.Bus",
+       "--talk-name=org.freedesktop.secrets",
         "--env=RUST_LOG=fractal=debug",
         "--env=G_MESSAGES_DEBUG=none"
     ],
diff --git a/src/login.rs b/src/login.rs
index 7f3c646d..1c689f97 100644
--- a/src/login.rs
+++ b/src/login.rs
@@ -1,3 +1,4 @@
+use crate::secret;
 use crate::FrctlSession;
 
 use adw;
@@ -121,7 +122,23 @@ impl FrctlLogin {
         self.freeze();
 
         let session = FrctlSession::new(homeserver);
+        self.setup_session(&session);
+        session.login_with_password(username, password);
+    }
+
+    pub fn restore_sessions(&self) -> Result<(), secret_service::Error> {
+        let sessions = secret::restore_sessions()?;
+
+        for (homeserver, stored_session) in sessions {
+            let session = FrctlSession::new(homeserver.to_string());
+            self.setup_session(&session);
+            session.login_with_previous_session(stored_session);
+        }
 
+        Ok(())
+    }
+
+    fn setup_session(&self, session: &FrctlSession) {
         session.connect_ready(clone!(@weak self as obj, @strong session => move |_| {
             if let Some(error) = session.get_error() {
                 let error_message = &imp::FrctlLogin::from_instance(&obj).error_message;
@@ -137,8 +154,6 @@ impl FrctlLogin {
                 obj.clean();
             }
         }));
-
-        session.login_with_password(username, password);
     }
 
     fn clean(&self) {
diff --git a/src/main.rs b/src/main.rs
index 5bdefb59..4bd454f9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,6 +3,7 @@ mod application;
 mod config;
 
 mod login;
+mod secret;
 mod session;
 mod window;
 
diff --git a/src/meson.build b/src/meson.build
index befbf1f3..d03ab188 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -24,6 +24,7 @@ sources = files(
   'main.rs',
   'window.rs',
   'login.rs',
+  'secret.rs',
   'session/mod.rs',
   'session/content.rs',
   'session/sidebar.rs',
diff --git a/src/secret.rs b/src/secret.rs
new file mode 100644
index 00000000..68ca4877
--- /dev/null
+++ b/src/secret.rs
@@ -0,0 +1,69 @@
+use secret_service::EncryptionType;
+use secret_service::SecretService;
+use std::collections::HashMap;
+
+/// Retrives all sessions stored to the `SecretService`
+pub fn restore_sessions() -> Result<Vec<(String, matrix_sdk::Session)>, secret_service::Error> {
+    use std::convert::TryInto;
+
+    let ss = SecretService::new(EncryptionType::Dh)?;
+    let collection = ss.get_default_collection()?;
+
+    // Sessions that contain or produce errors are ignored.
+    // TODO: Return error for corrupt sessions
+    let res = collection
+        .get_all_items()?
+        .iter()
+        .filter_map(|item| {
+            let attr = item.get_attributes().ok()?;
+            if let (Some(homeserver), Some(access_token), Some(user_id), Some(device_id)) = (
+                attr.get("homeserver"),
+                String::from_utf8(item.get_secret().ok()?).ok(),
+                attr.get("user-id")
+                    .and_then(|s| s.to_string().try_into().ok()),
+                attr.get("device-id")
+                    .and_then(|s| Some(s.to_string().into())),
+            ) {
+                let session = matrix_sdk::Session {
+                    access_token,
+                    user_id,
+                    device_id,
+                };
+                Some((homeserver.to_string(), session))
+            } else {
+                None
+            }
+        })
+        .collect();
+
+    Ok(res)
+}
+
+/// Writes a sessions to the `SecretService`, overwriting any previously stored session with the
+/// same `homeserver`, `username` and `device-id`.
+pub fn store_session(
+    homeserver: &str,
+    session: matrix_sdk::Session,
+) -> Result<(), secret_service::Error> {
+    let ss = SecretService::new(EncryptionType::Dh)?;
+    let collection = ss.get_default_collection()?;
+
+    let attributes: HashMap<&str, &str> = [
+        ("user-id", session.user_id.as_str()),
+        ("homeserver", homeserver),
+        ("device-id", session.device_id.as_str()),
+    ]
+    .iter()
+    .cloned()
+    .collect();
+
+    collection.create_item(
+        "Fractal",
+        attributes,
+        session.access_token.as_bytes(),
+        true,
+        "text/plain",
+    )?;
+
+    Ok(())
+}
diff --git a/src/session/mod.rs b/src/session/mod.rs
index 57c9ee8a..9f38105a 100644
--- a/src/session/mod.rs
+++ b/src/session/mod.rs
@@ -4,6 +4,7 @@ mod sidebar;
 use self::content::FrctlContent;
 use self::sidebar::FrctlSidebar;
 
+use crate::secret;
 use crate::RUNTIME;
 
 use adw;
@@ -171,8 +172,11 @@ impl FrctlSession {
         RUNTIME.block_on(async {
             tokio::spawn(async move {
                 let success = match method {
-                    CreationMethod::SessionRestore(_session) => {
-                        todo!("Implement session restore")
+                    CreationMethod::SessionRestore(session) => {
+                        let res = client.restore_login(session).await;
+                        let success = res.is_ok();
+                        send!(sender, res.map(|_| None));
+                        success
                     }
                     CreationMethod::Password(username, password) => {
                         // FIXME: client won't return if the homeserver isn't any real domain, I think
@@ -197,7 +201,7 @@ impl FrctlSession {
                         let response = response.unwrap();
 
                         let success = response.is_ok();
-                        send!(sender, response);
+                        send!(sender, response.map(|r| Some(r)));
                         success
                     }
                 };
@@ -220,9 +224,9 @@ impl FrctlSession {
         });
     }
 
-    fn setup(&self) -> glib::SyncSender<matrix_sdk::Result<login::Response>> {
+    fn setup(&self) -> glib::SyncSender<matrix_sdk::Result<Option<login::Response>>> {
         let (sender, receiver) = glib::MainContext::sync_channel::<
-            matrix_sdk::Result<login::Response>,
+            matrix_sdk::Result<Option<login::Response>>,
         >(Default::default(), 100);
         receiver.attach(
             None,
@@ -232,14 +236,16 @@ impl FrctlSession {
                         let priv_ = &imp::FrctlSession::from_instance(&obj);
                         priv_.error.replace(Some(error));
                     }
-                    Ok(response) => {
-                        // TODO: store this session to the SecretService so we can use it for the next login
-                        let _session = matrix_sdk::Session {
+                    Ok(Some(response)) => {
+                        let session = matrix_sdk::Session {
                             access_token: response.access_token,
                             user_id: response.user_id,
                             device_id: response.device_id,
                         };
+                        //TODO: set error to this error
+                        obj.store_session(session).unwrap();
                     }
+                    Ok(None) => {}
                 }
 
                 obj.emit_by_name("ready", &[]).unwrap();
@@ -268,4 +274,10 @@ impl FrctlSession {
         })
         .unwrap()
     }
+
+    fn store_session(&self, session: matrix_sdk::Session) -> Result<(), secret_service::Error> {
+        let priv_ = &imp::FrctlSession::from_instance(self);
+        let homeserver = priv_.homeserver.get().unwrap();
+        secret::store_session(homeserver, session)
+    }
 }
diff --git a/src/window.rs b/src/window.rs
index bbae15ee..05d56a3c 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -61,6 +61,12 @@ mod imp {
 
             // load latest window state
             obj.load_window_size();
+
+            // TODO: tell user that a stored session couldn't be restored
+            let result = self.login.restore_sessions();
+            if let Err(error) = result {
+                warn!("Failed to restore a session: {:?}", error);
+            }
             self.login.connect_new_session(
                 clone!(@weak obj => move |_login, session| obj.add_session(session)),
             );


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]