blob: 0c860790bff044de8bce33ffc68cc7bd9efbe08b [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.component.sandbox;
using zx;
using fuchsia.io;
/// Maximum number of bytes in a [DataCapability].
const MAX_DATA_LENGTH uint32 = 8192;
/// Maximum number of items returned by [DictionaryItemIterator].
const MAX_DICTIONARY_ITEMS_CHUNK uint32 = 128;
/// Maximum number of items returned by [DictionaryKeyIterator].
const MAX_DICTIONARY_KEYS_CHUNK uint32 = 128;
@available(added=HEAD)
type OneShotHandle = resource struct {
token zx.Handle:EVENTPAIR;
};
@available(added=HEAD)
type DataCapability = flexible union {
1: bytes vector<byte>:MAX_DATA_LENGTH;
2: string string:MAX_DATA_LENGTH;
3: int64 int64;
4: uint64 uint64;
};
@available(added=HEAD)
type Connector = resource struct {
token zx.Handle:EVENTPAIR;
};
@available(added=HEAD)
type Capability = flexible resource union {
1: unit @generated_name("UnitCapability") struct {};
2: handle OneShotHandle;
3: data DataCapability;
4: dictionary client_end:Dictionary;
5: connector Connector;
6: directory client_end:fuchsia.io.Directory;
7: router client_end:Router;
};
/// The maximum length of a dictionary key. This should coincide with
/// fuchsia.component.MAX_NAME_LENGTH.
@available(added=HEAD)
const MAX_NAME_LENGTH uint64 = fuchsia.io.MAX_NAME_LENGTH;
/// The key of a [`DictionaryItem`]. The constraints for valid keys are documented at
/// https://fuchsia.dev/reference/cml#names.
@available(added=HEAD)
alias DictionaryKey = string:MAX_NAME_LENGTH;
/// A key-value pair in a [`Dictionary`].
@available(added=HEAD)
type DictionaryItem = resource struct {
key DictionaryKey;
value Capability;
};
/// Error returned from methods in [`Dictionary`].
@available(added=HEAD)
type DictionaryError = flexible enum {
/// The Dictionary does not contain an item with the given key.
NOT_FOUND = 1;
/// The Dictionary already contains an item with the given key.
ALREADY_EXISTS = 2;
/// The Capability is invalid.
///
/// Capabilities must be created by sandbox, via
/// `fuchsia.component.sandbox.Factory` or returned from other
/// Component Framework APIs.
BAD_CAPABILITY = 3;
/// The key is invalid. The constraints for valid keys are documented at
/// https://fuchsia.dev/reference/cml#names.
INVALID_KEY = 4;
};
@discoverable
@available(added=20)
open protocol Dictionary {
/// Inserts a key-value pair into the dictionary.
///
/// * error `DictionaryError.ALREADY_EXISTS` if the dictionary already contains an
/// item with the same key.
@available(added=HEAD)
flexible Insert(DictionaryItem) -> () error DictionaryError;
/// Get a clone of a capability from this dictionary.
///
/// * error `DictionaryError.NOT_FOUND` if the dictionary does not contain the key.
@available(added=HEAD)
flexible Get(struct {
key DictionaryKey;
}) -> (resource struct {
capability Capability;
}) error DictionaryError;
/// Removes a key from the dictionary, returning the [`Capability`] value.
///
/// * error `DictionaryError.NOT_FOUND` if the dictionary does not contain the key.
@available(added=HEAD)
flexible Remove(struct {
key DictionaryKey;
}) -> (resource struct {
capability Capability;
}) error DictionaryError;
/// Creates a new connection to the same underlying dictionary.
///
/// Use `Copy` to a new dictionary with clones of all the exiting entries.
@available(added=HEAD)
flexible Clone() -> (resource struct {
dictionary client_end:Dictionary;
});
/// Create a new dictionary that contains a clone of all the entries in
/// this dictionary.
///
/// For example, if this dictionary contains nested dictionaries, the newly
/// created dictionary will contain references to those same nested
/// dictionaries because the entries are cloned rather than copied.
@available(added=HEAD)
flexible Copy() -> (resource struct {
dictionary client_end:Dictionary;
});
/// Enumerates the items in this dictionary.
///
/// Creates a clone of each item during enumeration.
@available(added=HEAD)
flexible Enumerate(resource struct {
iterator server_end:DictionaryItemIterator;
});
/// Enumerates the keys in this dictionary.
@available(added=HEAD)
flexible Keys(resource struct {
iterator server_end:DictionaryKeyIterator;
});
/// Removes all the entries in this dictionary.
///
/// If `contents` is not provided, all the items are discarded without
/// enumerating them.
@available(added=HEAD)
flexible Drain(resource struct {
iterator server_end:<DictionaryItemIterator, optional>;
});
};
@available(added=HEAD)
open protocol DictionaryItemIterator {
flexible GetNext() -> (resource struct {
items vector<DictionaryItem>:MAX_DICTIONARY_ITEMS_CHUNK;
});
};
@available(added=HEAD)
open protocol DictionaryKeyIterator {
flexible GetNext() -> (resource struct {
keys vector<DictionaryKey>:MAX_DICTIONARY_KEYS_CHUNK;
});
};
/// This represents a component within the framework.
/// There are currently no methods here as this is used as a token.
@available(added=HEAD)
type ComponentToken = resource struct {
token zx.Handle:EVENTPAIR;
};
/// A request for a route.
@available(added=HEAD)
type RouteRequest = resource table {
/// The requested availability for this capability.
1: availability Availability;
/// The component that is requesting the capability.
2: requesting ComponentToken;
};
@available(added=HEAD)
type RouterError = flexible enum : uint32 {
/// The router failed to find the capability.
NOT_FOUND = 1;
/// The arguments provided to the function are invalid.
INVALID_ARGS = 2;
};
/// A router allows a client to request a capability.
@discoverable
@available(added=HEAD)
open protocol Router {
flexible Route(RouteRequest) -> (resource struct {
capability Capability;
}) error RouterError;
};
/// A receiver is served by clients and allows them to receive channels
/// from the framework.
@discoverable
@available(added=HEAD)
open protocol Receiver {
/// Sends a channel to this receiver.
flexible Receive(ProtocolPayload);
};
/// Contains a protocol open request.
@available(added=HEAD)
type ProtocolPayload = resource struct {
channel zx.Handle:CHANNEL;
};
@available(added=HEAD)
type FactoryError = flexible enum : uint32 {
/// An invalid argument was passed.
INVALID_ARGS = 1;
/// The requested resource was unavailable.
UNAVAILABLE = 2;
};
/// The [`Factory`] protocol handles:
///
/// - Instantiation of sandbox types.
/// - Controlling sandbox objects given tokens.
///
@discoverable
@available(added=HEAD)
open protocol Factory {
/// Open a connection from the provided [Connector] capability.
///
/// If there is an error, it will be reported as a zx.Status epitaph on `server_end`.
/// Errors:
///
/// - `INVALID_ARGS`: `capability` is not a recognized [Connector].
flexible OpenConnector(resource struct {
capability Connector;
server_end zx.Handle:CHANNEL;
});
/// Extract the handle owned by the underlying `capability`, if it wasn't taken already.
///
/// Errors:
///
/// - `INVALID_ARGS`: `capability` does not contain a recognized [OneShotHandle] token.
/// - `UNAVAILABLE`: The underlying handle was already taken.h
flexible TakeHandle(resource struct {
capability OneShotHandle;
}) -> (resource struct {
handle zx.Handle;
}) error FactoryError;
/// Creates a `Connector` from a client served `Receiver`.
flexible CreateConnector(resource struct {
receiver client_end:Receiver;
}) -> (resource struct {
capability Connector;
});
/// Creates a `OneShotHandle` from the provided `handle`.
flexible CreateOneShotHandle(resource struct {
handle zx.Handle;
}) -> (resource struct {
capability OneShotHandle;
});
/// Creates a new empty [`Dictionary`].
flexible CreateDictionary() -> (resource struct {
dictionary client_end:Dictionary;
});
};