fix(permissions): make profile snapshots authoritative
This commit is contained in:
@@ -156,6 +156,74 @@ fn live_sidecar_rejects_oversized_frame_dimensions() -> Result<(), Box<dyn Error
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn live_sidecar_rejects_duplicate_permission_snapshot_entries() -> Result<(), Box<dyn Error>> {
|
||||
let root = TestDirectory::new()?;
|
||||
let profile_id = ProfileId::new();
|
||||
let tab_id = TabId::new();
|
||||
let mut sidecar = Sidecar::spawn(root.path())?;
|
||||
let mut ensure = ensure_request(&tab_id, &profile_id, "about:blank");
|
||||
ensure["site_permissions"] = json!([
|
||||
{
|
||||
"origin": "https://example.com",
|
||||
"feature": "camera",
|
||||
"state": "allow-always",
|
||||
"revision": 1,
|
||||
},
|
||||
{
|
||||
"origin": "https://example.com",
|
||||
"feature": "camera",
|
||||
"state": "deny-always",
|
||||
"revision": 2,
|
||||
},
|
||||
]);
|
||||
|
||||
let response = sidecar.exchange(&ensure)?;
|
||||
|
||||
assert!(response.error.as_deref().is_some_and(|error| error.contains("duplicate permission")));
|
||||
sidecar.shutdown()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn live_sidecar_accepts_permission_snapshot_lifecycle() -> Result<(), Box<dyn Error>> {
|
||||
let root = TestDirectory::new()?;
|
||||
let profile_id = ProfileId::new();
|
||||
let tab_id = TabId::new();
|
||||
let mut sidecar = Sidecar::spawn(root.path())?;
|
||||
let mut ensure = ensure_request(&tab_id, &profile_id, "about:blank");
|
||||
|
||||
for (generation, state, revision) in [(1, "allow-once", 1), (2, "transferred-allow-once", 2)] {
|
||||
ensure["site_permission_generation"] = json!(generation);
|
||||
ensure["site_permissions"] = json!([{
|
||||
"origin": "https://example.com",
|
||||
"feature": "camera",
|
||||
"state": state,
|
||||
"revision": revision,
|
||||
}]);
|
||||
let response = sidecar.exchange(&ensure)?;
|
||||
assert!(response.error.is_none(), "state={state} error={:?}", response.error);
|
||||
}
|
||||
|
||||
ensure["site_permission_generation"] = json!(3);
|
||||
ensure["site_permissions"] = json!([]);
|
||||
let response = sidecar.exchange(&ensure)?;
|
||||
assert!(response.error.is_none(), "empty snapshot error={:?}", response.error);
|
||||
|
||||
ensure["site_permission_generation"] = json!(1);
|
||||
ensure["site_permissions"] = json!([{
|
||||
"origin": "https://example.com",
|
||||
"feature": "camera",
|
||||
"state": "allow-once",
|
||||
"revision": 1,
|
||||
}]);
|
||||
let response = sidecar.exchange(&ensure)?;
|
||||
assert!(response.error.is_none(), "stale snapshot error={:?}", response.error);
|
||||
|
||||
sidecar.shutdown()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "hardware-render", target_os = "macos"))]
|
||||
#[test]
|
||||
fn hardware_sidecar_transfers_a_real_iosurface_mach_descriptor() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
@@ -19,7 +19,7 @@ use serde_json::{Value, json};
|
||||
pub(super) const WIDTH: u32 = 360;
|
||||
pub(super) const HEIGHT: u32 = 240;
|
||||
pub(super) const RESPONSE_TIMEOUT: Duration = Duration::from_secs(20);
|
||||
pub(super) const LIVE_PROTOCOL_VERSION: u32 = 2;
|
||||
pub(super) const LIVE_PROTOCOL_VERSION: u32 = 3;
|
||||
pub(super) const MAX_FRAME_DIMENSION: u32 = 16_384;
|
||||
const MAX_FRAME_BYTE_COUNT: usize = 256 * 1024 * 1024;
|
||||
|
||||
@@ -33,6 +33,7 @@ pub(super) fn ensure_request(tab_id: &TabId, profile_id: &ProfileId, url: &str)
|
||||
"height": HEIGHT,
|
||||
"page_zoom_percent": 100,
|
||||
"device_pixel_ratio": 1.0,
|
||||
"site_permission_generation": 0,
|
||||
"site_permissions": [],
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@ use std::{
|
||||
use ely_domain::{ProfileId, SiteOrigin, SitePermissionFeature, TabId, UrlText};
|
||||
use ely_servo_host::{
|
||||
HidpiScaleRequest, KeyboardTextRequest, MouseClickRequest, MouseDragRequest, NavigationRequest,
|
||||
PageZoomRequest, PermissionDecision, PermissionRequest, ResizeRequest, ScrollRequest,
|
||||
ServoHost, ServoHostError, ServoSurfaceSize, SoftwareServoHost, TouchTapRequest, WebViewState,
|
||||
PageZoomRequest, PermissionDecision, PermissionSnapshotEntry, PermissionSnapshotRequest,
|
||||
PermissionSnapshotState, ResizeRequest, ScrollRequest, ServoHost, ServoHostError,
|
||||
ServoSurfaceSize, SoftwareServoHost, TouchTapRequest, WebViewState,
|
||||
};
|
||||
|
||||
const MINIMUM_CONTENT_PIXELS: u64 = 1_000;
|
||||
@@ -202,25 +203,29 @@ fn exercise_real_servo_webview_lifecycle() -> Result<(), Box<dyn Error>> {
|
||||
assert_eq!(snapshot.profile_id(), &profile_id);
|
||||
assert_eq!(snapshot.state(), &WebViewState::Created);
|
||||
|
||||
host.set_permission(
|
||||
PermissionRequest {
|
||||
webview_id: webview_id.clone(),
|
||||
profile_id: profile_id.clone(),
|
||||
host.replace_permissions(PermissionSnapshotRequest {
|
||||
webview_id: webview_id.clone(),
|
||||
profile_id: profile_id.clone(),
|
||||
generation: 1,
|
||||
entries: vec![PermissionSnapshotEntry {
|
||||
origin: SiteOrigin::parse("https://example.com")?,
|
||||
feature: SitePermissionFeature::Camera,
|
||||
},
|
||||
PermissionDecision::AllowOnce,
|
||||
)?;
|
||||
state: PermissionSnapshotState::Decision(PermissionDecision::AllowOnce),
|
||||
revision: 1,
|
||||
}],
|
||||
})?;
|
||||
let other_profile_id = ProfileId::new();
|
||||
let mismatch = host.set_permission(
|
||||
PermissionRequest {
|
||||
webview_id: webview_id.clone(),
|
||||
profile_id: other_profile_id.clone(),
|
||||
let mismatch = host.replace_permissions(PermissionSnapshotRequest {
|
||||
webview_id: webview_id.clone(),
|
||||
profile_id: other_profile_id.clone(),
|
||||
generation: 2,
|
||||
entries: vec![PermissionSnapshotEntry {
|
||||
origin: SiteOrigin::parse("https://example.com")?,
|
||||
feature: SitePermissionFeature::Camera,
|
||||
},
|
||||
PermissionDecision::AllowAlways,
|
||||
);
|
||||
state: PermissionSnapshotState::Decision(PermissionDecision::AllowAlways),
|
||||
revision: 1,
|
||||
}],
|
||||
});
|
||||
assert!(
|
||||
matches!(
|
||||
mismatch,
|
||||
|
||||
Reference in New Issue
Block a user