Skip to content

Commit aab1633

Browse files
committed
Merge branch 'main' into multiple_devices
2 parents 9ab53aa + 6f80c1b commit aab1633

20 files changed

Lines changed: 277 additions & 50 deletions

File tree

.github/workflows/main.yml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,26 @@ jobs:
1818
- name: Install system dependencies
1919
run: |
2020
sudo apt install -y --no-install-recommends \
21-
curl git build-essential meson \
21+
curl git build-essential \
2222
libgtk-4-dev gettext libdbus-1-dev libssl-dev libudev-dev \
23-
libxml2-utils desktop-file-utils
23+
libxml2-utils desktop-file-utils \
24+
python3-pip ninja-build
25+
- name: Install Meson
26+
run: |
27+
# Newer version needed for --interactive flag needed below
28+
python3 -m pip install --user -v 'meson==1.5.0'
2429
- name: Setup meson project
2530
run: meson setup build
2631
- name: Build
2732
run: ninja -C build
33+
- name: Test
34+
# We have to use the --interactive flag because of some
35+
# weird issue with meson hanging after cargo exits due to the TestDBus.
36+
# Probably has to do with forking the test processes.
37+
run: meson test --interactive
38+
working-directory: build/
39+
- name: Check clippy recommendations
40+
run: env CARGO_HOME=build/cargo-home cargo clippy --manifest-path xyz-iinuwa-credential-manager-portal-gtk/Cargo.toml --target-dir build/xyz-iinuwa-credential-manager-portal-gtk/src
41+
- name: Check formatting
42+
run: cargo fmt --check
43+
working-directory: xyz-iinuwa-credential-manager-portal-gtk

contrib/xyz.iinuwa.credentials.CredentialManager.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
<arg name="request" type="a{sv}" direction="in"/>
1717
<arg type="a{sv}" direction="out"/>
1818
</method>
19+
<method name="GetClientCapabilities">
20+
<arg type="a{sv}" direction="out"/>
21+
</method>
1922
</interface>
2023
<interface name="org.freedesktop.DBus.Peer">
2124
<method name="Ping">

demo_client/main.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ async def run(cmd):
5252
elif cmd == 'get':
5353
user_data = json.load(open('./user.json', 'r'))
5454
cred_id = util.b64_decode(user_data['cred_id'])
55-
auth_data = await get_passkey(interface, origin, is_same_origin, rp_id, cred_id, user_data)
55+
auth_data = await get_passkey(interface, origin, top_origin, rp_id, cred_id, user_data)
5656
print(auth_data)
5757
else:
5858
print(f"unknown cmd: {cmd}")
@@ -140,7 +140,8 @@ async def create_passkey(interface, origin, top_origin, rp_id, user_handle, user
140140
return webauthn.verify_create_response(response_json, options, origin)
141141

142142

143-
async def get_passkey(interface, origin, is_same_origin, rp_id, cred_id, user: Optional[dict]):
143+
async def get_passkey(interface, origin, top_origin, rp_id, cred_id, user: Optional[dict]):
144+
is_same_origin = origin == top_origin
144145
options = {
145146
"challenge": util.b64_encode(secrets.token_bytes(16)),
146147
"rpId": rp_id,

meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ project(
22
'xyz-iinuwa-credential-manager-portal-gtk',
33
'rust',
44
version: '0.1.0',
5-
meson_version: '>= 0.60',
5+
meson_version: '>= 1.5.0',
66
# license: 'MIT',
77
)
88

webext/add-on/background.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,16 @@ function rcvFromContent(msg) {
3636
// const isCrossOrigin = origin === topOrigin
3737
// const isTopLevel = contentPort.sender.frameId === 0;
3838

39-
40-
const serializedOptions = serializeRequest(options)
41-
42-
console.debug(options.publicKey.challenge)
43-
console.debug("background script received options, passing onto native app")
44-
nativePort.postMessage({ requestId, cmd, options: serializedOptions, origin, topOrigin })
39+
if (options) {
40+
const serializedOptions = serializeRequest(options)
41+
42+
console.debug(options.publicKey.challenge)
43+
console.debug("background script received options, passing onto native app")
44+
nativePort.postMessage({ requestId, cmd, options: serializedOptions, origin, topOrigin })
45+
} else {
46+
console.debug("background script received message without arguments, passing onto native app")
47+
nativePort.postMessage({ requestId, cmd, origin, topOrigin })
48+
}
4549
}
4650

4751
function rcvFromNative(msg) {

webext/add-on/content.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ exportFunction(createCredential, navigator.credentials, { defineAs: "create"})
1414
exportFunction(getCredential, navigator.credentials, { defineAs: "get"})
1515

1616

17+
if (window.PublicKeyCredential) {
18+
console.log("overriding PublicKeyCredential.getClientCapabilities() in content script");
19+
exportFunction(getClientCapabilities, PublicKeyCredential, { defineAs: "getClientCapabilities"})
20+
}
21+
1722
function startRequest() {
1823
const requestId = requestCounter++;
1924
const {promise, resolve, reject } = window.Promise.withResolvers();
@@ -182,3 +187,10 @@ function getCredential(request) {
182187
webauthnPort.postMessage({ requestId, cmd: 'get', options, })
183188
return promise.then(cloneCredentialResponse)
184189
};
190+
191+
function getClientCapabilities() {
192+
console.log("forwarding getClientCapabilities call from content script to background script")
193+
const { requestId, promise } = startRequest();
194+
webauthnPort.postMessage({ requestId, cmd: 'getClientCapabilities', })
195+
return promise.then((capabilities) => cloneInto(capabilities, window))
196+
};

webext/app/credential_manager_shim.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ async def run(cmd, options, origin, top_origin):
343343

344344
interface = proxy_object.get_interface(
345345
'xyz.iinuwa.credentials.CredentialManagerUi1')
346-
logging.debug(f"COnnected to interface at {interface.path}")
346+
logging.debug(f"Connected to interface at {interface.path}")
347347

348348
if cmd == 'create':
349349
if 'publicKey' in options:
@@ -355,6 +355,12 @@ async def run(cmd, options, origin, top_origin):
355355
return await get_passkey(interface, options['publicKey'], origin, top_origin)
356356
else:
357357
raise Exception(f"Could not get unknown credential type: {options.keys()[0]}")
358+
elif cmd == 'getClientCapabilities':
359+
rsp = await interface.call_get_client_capabilities()
360+
response = {}
361+
for name, val in rsp.items():
362+
response[name] = val.value
363+
return response
358364
else:
359365
raise Exception(f"unknown cmd: {cmd}")
360366

@@ -366,7 +372,10 @@ async def run(cmd, options, origin, top_origin):
366372
request_id = receivedMessage['requestId']
367373
try:
368374
cmd = receivedMessage['cmd']
369-
options = receivedMessage['options']
375+
376+
options = None
377+
if 'options' in receivedMessage:
378+
options = receivedMessage['options']
370379
origin = receivedMessage['origin']
371380
top_origin = receivedMessage['topOrigin']
372381
loop = asyncio.get_event_loop()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
src/config.rs
2+
tests/config/mod.rs

xyz-iinuwa-credential-manager-portal-gtk/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ endif
6565
subdir('data')
6666
subdir('po')
6767
subdir('src')
68+
subdir('tests')
6869

6970
gnome.post_install(
7071
gtk_update_icon_cache: true,

xyz-iinuwa-credential-manager-portal-gtk/src/application.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,13 @@ mod imp {
5757
vm2.clone().connect_completed_notify(move |vm| {
5858
if vm.completed() {
5959
glib::spawn_future_local(clone!(
60-
#[weak] window2,
60+
#[weak]
61+
window2,
6162
async move {
6263
// Wait to show confirmation before closing.
6364
async_std::task::sleep(Duration::from_millis(500)).await;
64-
gtk::prelude::WidgetExt::activate_action(&window2, "window.close", None).unwrap()
65+
gtk::prelude::WidgetExt::activate_action(&window2, "window.close", None)
66+
.unwrap()
6567
}
6668
));
6769
}

0 commit comments

Comments
 (0)