Merge pull request 'Call page on its own origin, http://127.0.0.1:44548 (cinny #43)' (#27) from desktop-call-origin into main
Build Lotus Chat Desktop / prepare (push) Canceled after 0s
Build Lotus Chat Desktop / build-windows (push) Canceled after 0s
Build Lotus Chat Desktop / build-linux (push) Canceled after 0s
Build Lotus Chat Desktop / build-arch (push) Canceled after 0s
Build Lotus Chat Desktop / update-manifest (push) Canceled after 0s
Build Lotus Chat Desktop / prepare (push) Canceled after 0s
Build Lotus Chat Desktop / build-windows (push) Canceled after 0s
Build Lotus Chat Desktop / build-linux (push) Canceled after 0s
Build Lotus Chat Desktop / build-arch (push) Canceled after 0s
Build Lotus Chat Desktop / update-manifest (push) Canceled after 0s
Merge pull request #27: call page on its own origin, http://127.0.0.1:44548 (cinny #43)
This commit was merged in pull request #27.
This commit is contained in:
+11
-1
@@ -1006,7 +1006,17 @@ pub fn run() {
|
||||
native::hotkeys::global_hotkeys_supported,
|
||||
native::hotkeys::set_global_hotkeys,
|
||||
])
|
||||
.plugin(tauri_plugin_localhost::Builder::new(port).build())
|
||||
// Bound to 127.0.0.1 explicitly (cinny #43). The app is still loaded as
|
||||
// http://localhost:{port} (its storage lives under that origin, and the
|
||||
// engines try 127.0.0.1 for `localhost`); the bundled call page is
|
||||
// loaded as http://127.0.0.1:{port}, a separate origin on the same
|
||||
// server. Binding the name `localhost` could pick ::1 only (Windows
|
||||
// lists it first), and then the call page wouldn't load.
|
||||
.plugin(
|
||||
tauri_plugin_localhost::Builder::new(port)
|
||||
.host("127.0.0.1")
|
||||
.build(),
|
||||
)
|
||||
.plugin(
|
||||
// DECORATIONS is excluded: the custom-chrome toggle (set_custom_chrome)
|
||||
// owns the decorated flag. Letting window-state restore a saved
|
||||
|
||||
@@ -12,8 +12,13 @@
|
||||
//! - WebKitGTK doesn't say which frame asked; the check is on the page loaded
|
||||
//! in the window. Frames are gated before the request gets this far by the
|
||||
//! Permissions Policy: cinny only puts `microphone; camera` in the `allow=`
|
||||
//! of the call frame (same origin on desktop), and cross-origin frames get
|
||||
//! neither location nor notifications.
|
||||
//! of the call frame, and cross-origin frames get neither location nor
|
||||
//! notifications.
|
||||
//!
|
||||
//! The call frame (cinny #43): the bundled Element Call page is loaded from
|
||||
//! `http://127.0.0.1:{port}`, the same local server on a second origin, so it
|
||||
//! can't reach the app's storage. WebView2 reports that origin for the call's
|
||||
//! microphone/camera requests; it gets media and nothing else.
|
||||
|
||||
use tauri::Url;
|
||||
|
||||
@@ -57,6 +62,14 @@ pub(crate) fn decide(kind: Kind, uri: &str, app: &AppOrigins, grants: &[Kind]) -
|
||||
if kind == Kind::Other {
|
||||
return Decision::Default;
|
||||
}
|
||||
if app.is_call_frame(uri) {
|
||||
// The call page: microphone/camera/screen only.
|
||||
return if kind == Kind::Media && grants.contains(&kind) {
|
||||
Decision::Allow
|
||||
} else {
|
||||
Decision::Deny
|
||||
};
|
||||
}
|
||||
if !app.contains(uri) {
|
||||
return Decision::Deny;
|
||||
}
|
||||
@@ -76,9 +89,12 @@ fn origin_of(uri: &str) -> Option<Origin> {
|
||||
Some((url.scheme().to_owned(), host, url.port_or_known_default()))
|
||||
}
|
||||
|
||||
/// The origins the app's own page is served from.
|
||||
/// The origins the app's own page is served from, and the call page's.
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct AppOrigins(Vec<Origin>);
|
||||
pub(crate) struct AppOrigins {
|
||||
app: Vec<Origin>,
|
||||
call: Option<Origin>,
|
||||
}
|
||||
|
||||
impl AppOrigins {
|
||||
/// Release builds load `http://localhost:{port}` (tauri-plugin-localhost).
|
||||
@@ -93,11 +109,20 @@ impl AppOrigins {
|
||||
uris.push(dev.to_string());
|
||||
}
|
||||
}
|
||||
Self(uris.iter().filter_map(|u| origin_of(u)).collect())
|
||||
Self {
|
||||
app: uris.iter().filter_map(|u| origin_of(u)).collect(),
|
||||
call: origin_of(&format!("http://127.0.0.1:{port}/")),
|
||||
}
|
||||
}
|
||||
|
||||
/// The app's own page.
|
||||
pub(crate) fn contains(&self, uri: &str) -> bool {
|
||||
origin_of(uri).is_some_and(|o| self.0.contains(&o))
|
||||
origin_of(uri).is_some_and(|o| self.app.contains(&o))
|
||||
}
|
||||
|
||||
/// The call page on its own origin (`http://127.0.0.1:{port}`).
|
||||
pub(crate) fn is_call_frame(&self, uri: &str) -> bool {
|
||||
origin_of(uri).is_some_and(|o| self.call.as_ref() == Some(&o))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +229,33 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_frame_gets_media_only() {
|
||||
let app = app();
|
||||
let call = "http://127.0.0.1:44548/public/element-call/index.html?widgetId=x";
|
||||
assert!(app.is_call_frame(call));
|
||||
assert!(!app.contains(call));
|
||||
for grants in [LINUX_GRANTS, WINDOWS_GRANTS] {
|
||||
assert_eq!(decide(Kind::Media, call, &app, grants), Decision::Allow);
|
||||
for kind in [Kind::DeviceInfo, Kind::Notifications, Kind::Geolocation] {
|
||||
assert_eq!(decide(kind, call, &app, grants), Decision::Deny, "{kind:?}");
|
||||
}
|
||||
assert_eq!(decide(Kind::Other, call, &app, grants), Decision::Default);
|
||||
}
|
||||
for not_call in [
|
||||
"http://127.0.0.1:44549/",
|
||||
"https://127.0.0.1:44548/",
|
||||
"http://127.0.0.2:44548/",
|
||||
"http://[::1]:44548/",
|
||||
] {
|
||||
assert!(!app.is_call_frame(not_call), "{not_call}");
|
||||
assert_eq!(
|
||||
decide(Kind::Media, not_call, &app, WINDOWS_GRANTS),
|
||||
Decision::Deny
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn other_kinds_are_left_to_the_engine() {
|
||||
let app = app();
|
||||
|
||||
Reference in New Issue
Block a user