///|
pub struct CommandManifestEntry {
plugin : String
command : String
route : String
mode : CommandMode
affinity : CommandExecutionAffinity
permission : Permission
request_schema : IpcSchema
response_schema : IpcSchema
allowed_windows : Array[String]
allowed_origins : Array[String]
allowed_platforms : Array[String]
} derive(Debug, Eq)
///|
fn CommandManifestEntry::new(
plugin~ : String,
command~ : String,
mode~ : CommandMode,
affinity~ : CommandExecutionAffinity,
permission~ : Permission,
request_schema~ : IpcSchema,
response_schema~ : IpcSchema,
allowed_windows~ : Array[String],
allowed_origins~ : Array[String],
allowed_platforms~ : Array[String],
) -> CommandManifestEntry {
{
plugin,
command,
route: "\{plugin}.\{command}",
mode,
affinity,
permission,
request_schema,
response_schema,
allowed_windows: allowed_windows.copy(),
allowed_origins: allowed_origins.copy(),
allowed_platforms: allowed_platforms.copy(),
}
}
///|
pub fn CommandManifestEntry::plugin(self : CommandManifestEntry) -> String {
self.plugin
}
///|
pub fn CommandManifestEntry::command(self : CommandManifestEntry) -> String {
self.command
}
///|
pub fn CommandManifestEntry::route(self : CommandManifestEntry) -> String {
self.route
}
///|
pub fn CommandManifestEntry::mode(self : CommandManifestEntry) -> CommandMode {
self.mode
}
///|
pub fn CommandManifestEntry::affinity(
self : CommandManifestEntry,
) -> CommandExecutionAffinity {
self.affinity
}
///|
pub fn CommandManifestEntry::permission(
self : CommandManifestEntry,
) -> Permission {
self.permission
}
///|
pub fn CommandManifestEntry::request_schema(
self : CommandManifestEntry,
) -> IpcSchema {
self.request_schema
}
///|
pub fn CommandManifestEntry::response_schema(
self : CommandManifestEntry,
) -> IpcSchema {
self.response_schema
}
///|
pub fn CommandManifestEntry::allowed_windows(
self : CommandManifestEntry,
) -> Array[String] {
self.allowed_windows.copy()
}
///|
pub fn CommandManifestEntry::allowed_origins(
self : CommandManifestEntry,
) -> Array[String] {
self.allowed_origins.copy()
}
///|
pub fn CommandManifestEntry::allowed_platforms(
self : CommandManifestEntry,
) -> Array[String] {
self.allowed_platforms.copy()
}
///|
pub fn CommandManifestEntry::allowed_in_window(
self : CommandManifestEntry,
window_label : String,
) -> Bool {
self.allowed_windows.contains(window_label)
}
///|
pub fn CommandManifestEntry::allowed_for_origin(
self : CommandManifestEntry,
origin : String,
) -> Bool {
self.allowed_origins.is_empty() || self.allowed_origins.contains(origin)
}
///|
pub fn CommandManifestEntry::allowed_on_platform(
self : CommandManifestEntry,
platform : String,
) -> Bool {
self.allowed_platforms.is_empty() || self.allowed_platforms.contains(platform)
}
///|
pub fn CommandManifestEntry::to_json(self : CommandManifestEntry) -> String {
[
"{",
"\"plugin\":\{self.plugin.json_string()},",
"\"command\":\{self.command.json_string()},",
"\"route\":\{self.route.json_string()},",
"\"mode\":\{self.mode.name().json_string()},",
"\"affinity\":\{self.affinity.name().json_string()},",
"\"permission\":\{self.permission.name().json_string()},",
"\"requestSchema\":\{self.request_schema.to_json()},",
"\"responseSchema\":\{self.response_schema.to_json()},",
"\"allowedWindows\":[\{self.allowed_windows.map(fn(window) { window.json_string() }).join(",")}],",
"\"allowedOrigins\":[\{self.allowed_origins.map(fn(origin) { origin.json_string() }).join(",")}],",
"\"allowedPlatforms\":[\{self.allowed_platforms.map(fn(platform) { platform.json_string() }).join(",")}]",
"}",
].join("")
}
///|
pub struct CommandManifest {
entries : Array[CommandManifestEntry]
} derive(Debug, Eq)
///|
pub fn CommandManifest::new(
entries? : Array[CommandManifestEntry] = [],
) -> CommandManifest {
{ entries: entries.copy() }
}
///|
pub fn CommandManifest::from_plugins(
plugins~ : Array[Plugin],
capabilities~ : Array[Capability],
windows~ : Array[ResolvedWindow],
platform? : String = "",
) -> CommandManifest {
let entries : Array[CommandManifestEntry] = []
let policy = CapabilityPolicy::new(capabilities~)
for plugin in plugins {
for command in plugin.commands() {
let allowed_windows : Array[String] = []
for window in windows {
if policy.allows_window(
window_label=window.label(),
permission=command.permission(),
platform~,
) {
allowed_windows.push(window.label())
}
}
entries.push(
CommandManifestEntry::new(
plugin=plugin.name(),
command=command.name(),
mode=command.mode(),
affinity=command.affinity(),
permission=command.permission(),
request_schema=command.request_schema(),
response_schema=command.response_schema(),
allowed_windows~,
allowed_origins=command_allowed_origins(
policy,
allowed_windows,
command.permission(),
platform,
),
allowed_platforms=command_allowed_platforms(
policy,
allowed_windows,
command.permission(),
),
),
)
}
}
CommandManifest::new(entries~)
}
///|
fn command_allowed_origins(
policy : CapabilityPolicy,
windows : Array[String],
permission : Permission,
platform : String,
) -> Array[String] {
let origins : Array[String] = []
for window in windows {
let window_origins = policy.allowed_origins(
window_label=window,
permission~,
platform~,
)
if window_origins.is_empty() {
return []
}
for origin in window_origins {
if !origins.contains(origin) {
origins.push(origin)
}
}
}
origins
}
///|
fn command_allowed_platforms(
policy : CapabilityPolicy,
windows : Array[String],
permission : Permission,
) -> Array[String] {
let platforms : Array[String] = []
for capability in policy.capabilities() {
let permission_allowed = capability.permissions().contains(permission)
if permission_allowed &&
command_capability_applies_to_windows(capability, windows) {
let capability_platforms = capability.platforms()
if capability_platforms.is_empty() {
return []
}
for platform in capability_platforms {
if !platforms.contains(platform) {
platforms.push(platform)
}
}
}
}
platforms
}
///|
fn command_capability_applies_to_windows(
capability : Capability,
windows : Array[String],
) -> Bool {
if capability.windows().is_empty() {
return true
}
for window in windows {
if capability.windows().contains(window) {
return true
}
}
false
}
///|
pub fn CommandManifest::entries(
self : CommandManifest,
) -> Array[CommandManifestEntry] {
self.entries.copy()
}
///|
pub fn CommandManifest::routes(self : CommandManifest) -> Array[String] {
self.entries.map(fn(entry) { entry.route() })
}
///|
pub fn CommandManifest::entry(
self : CommandManifest,
route : String,
) -> CommandManifestEntry? {
for entry in self.entries {
if entry.route() == route {
return Some(entry)
}
}
None
}
///|
pub fn CommandManifest::routes_by_mode(
self : CommandManifest,
mode : CommandMode,
) -> Array[String] {
let routes : Array[String] = []
for entry in self.entries {
if entry.mode() == mode {
routes.push(entry.route())
}
}
routes
}
///|
pub fn CommandManifest::routes_by_affinity(
self : CommandManifest,
affinity : CommandExecutionAffinity,
) -> Array[String] {
let routes : Array[String] = []
for entry in self.entries {
if entry.affinity() == affinity {
routes.push(entry.route())
}
}
routes
}
///|
pub fn CommandManifest::allowed_routes(
self : CommandManifest,
window_label : String,
) -> Array[String] {
let routes : Array[String] = []
for entry in self.entries {
if entry.allowed_in_window(window_label) {
routes.push(entry.route())
}
}
routes
}
///|
pub fn CommandManifest::allows(
self : CommandManifest,
route : String,
window_label~ : String,
origin? : String = "",
platform? : String = "",
) -> Bool {
match self.entry(route) {
Some(entry) =>
entry.allowed_in_window(window_label) &&
entry.allowed_for_origin(origin) &&
entry.allowed_on_platform(platform)
None => false
}
}
///|
pub fn CommandManifest::to_json(self : CommandManifest) -> String {
[
"{",
"\"commands\":[\{self.entries.map(fn(entry) { entry.to_json() }).join(",")}]",
"}",
].join("")
}