mirror of
https://github.com/lexmount/moli.git
synced 2026-10-06 00:00:56 +00:00
feat(midi): expose secure non-constructible MIDI owner interfaces
This commit is contained in:
@@ -92,6 +92,12 @@ pub(in crate::context_bootstrap) const WORKER_SHARED_INTERFACE_NAMES: &[&str] =
|
||||
];
|
||||
|
||||
const SECURE_CONTEXT_ONLY_INTERFACE_NAMES: &[&str] = &[
|
||||
"MIDIPort",
|
||||
"MIDIAccess",
|
||||
"MIDIInput",
|
||||
"MIDIOutput",
|
||||
"MIDIInputMap",
|
||||
"MIDIOutputMap",
|
||||
"MediaDeviceInfo",
|
||||
"InputDeviceInfo",
|
||||
"DeviceMotionEvent",
|
||||
|
||||
@@ -392,6 +392,30 @@ const CONSTRUCTOR_SPECS_BEFORE_STREAMS: &[ConstructorSpec] = &[
|
||||
interface: web_api_interfaces::MessageChannel::DESCRIPTOR,
|
||||
kind: ConstructorKind::MessageChannel,
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::MIDIPort::DESCRIPTOR,
|
||||
kind: ConstructorKind::Illegal,
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::MIDIAccess::DESCRIPTOR,
|
||||
kind: ConstructorKind::Illegal,
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::MIDIInput::DESCRIPTOR,
|
||||
kind: ConstructorKind::Illegal,
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::MIDIOutput::DESCRIPTOR,
|
||||
kind: ConstructorKind::Illegal,
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::MIDIInputMap::DESCRIPTOR,
|
||||
kind: ConstructorKind::Illegal,
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::MIDIOutputMap::DESCRIPTOR,
|
||||
kind: ConstructorKind::Illegal,
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::MessagePort::DESCRIPTOR,
|
||||
kind: ConstructorKind::MessagePort,
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn midi_owner_interfaces_preserve_native_inheritance_and_realm_contracts() {
|
||||
for url in [
|
||||
"https://midi-owner-interfaces.test/",
|
||||
"http://midi-owner-interfaces.test/",
|
||||
"http://localhost/",
|
||||
] {
|
||||
let mut vm = new_storage_page_task_executor_test_vm(url);
|
||||
vm.eval("document.body.innerHTML = '<iframe id=child></iframe>'")
|
||||
.unwrap();
|
||||
assert_eq!(vm.eval(r#"(() => {
|
||||
const assert = (ok, message) => { if (!ok) throw Error(message); };
|
||||
const popup = open();
|
||||
assert(popup, 'popup test prerequisite');
|
||||
try {
|
||||
const realms = [window, document.getElementById('child').contentWindow, popup];
|
||||
for (const w of realms) {
|
||||
for (const [name, parentName] of [["MIDIPort","EventTarget"],["MIDIAccess","EventTarget"],["MIDIInput","MIDIPort"],["MIDIOutput","MIDIPort"],["MIDIInputMap","Object"],["MIDIOutputMap","Object"]]) {
|
||||
if (true && !w.isSecureContext) {
|
||||
assert(!(name in w), name + ' hidden in an insecure realm');
|
||||
continue;
|
||||
}
|
||||
const C = w[name], parent = w[parentName];
|
||||
assert(typeof C === 'function' && C.name === name && C.length === 0, name + ' interface object');
|
||||
const descriptor = Object.getOwnPropertyDescriptor(w, name);
|
||||
assert(descriptor.writable && descriptor.configurable && !descriptor.enumerable, name + ' global descriptor');
|
||||
assert(Object.getPrototypeOf(C.prototype) === parent.prototype, name + ' prototype inheritance');
|
||||
assert(Object.getPrototypeOf(C) === (parentName === 'Object' ? w.Function.prototype : parent), name + ' interface inheritance');
|
||||
assert(C.prototype.constructor === C, name + ' prototype constructor');
|
||||
const tag = Object.getOwnPropertyDescriptor(C.prototype, Symbol.toStringTag);
|
||||
assert(tag.value === name && !tag.writable && !tag.enumerable && tag.configurable, name + ' tag');
|
||||
for (const call of [() => C(), () => new C()]) {
|
||||
let error;
|
||||
try { call(); } catch (caught) { error = caught; }
|
||||
assert(error instanceof w.TypeError, name + ' rejects direct construction in the callee realm');
|
||||
if (w !== window) assert(!(error instanceof TypeError), name + ' foreign error realm');
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} finally { popup.close(); }
|
||||
})()"#).unwrap(), "true", "{url}");
|
||||
}
|
||||
}
|
||||
@@ -2152,6 +2152,7 @@ mod indexed_db;
|
||||
mod inspector_unwrap;
|
||||
mod lazy_storage;
|
||||
mod lazy_window_surfaces;
|
||||
mod midi_owner_interfaces;
|
||||
mod mouse_snapshot;
|
||||
mod no_cors_header_fill;
|
||||
mod observer_callbacks;
|
||||
|
||||
@@ -296,6 +296,12 @@ interfaces! {
|
||||
MediaQueryListEvent: Event;
|
||||
MediaSource: EventTarget;
|
||||
MemoryInfo;
|
||||
MIDIPort: EventTarget;
|
||||
MIDIAccess: EventTarget;
|
||||
MIDIInput: MIDIPort;
|
||||
MIDIOutput: MIDIPort;
|
||||
MIDIInputMap;
|
||||
MIDIOutputMap;
|
||||
MessageChannel;
|
||||
MessageEvent: Event;
|
||||
MessagePort: EventTarget;
|
||||
|
||||
Reference in New Issue
Block a user